您的位置:首页 > 其它

一个菜鸟学习C的路程(一)

2011-11-19 20:42 176 查看
2011年11月19日星期六

今天,下午睡觉的时候,突然间起来看见手机上有两天短息,一条是班长发的,一条是图书馆发的“尊敬的XX读者,您预约的<C语言深度解剖>已归还...”,当时就心情激动,本来还睡意蒙蒙的,马上带上电脑,骑着车去了图书馆。然后去了实验室,看是第二次阅读了,然后...我发现了附录有几道题,它说“请在40分钟...50分一下,请不要气馁...”,好吧,我十几分钟就做完了,并且上面还有好多题目是自己以前在CSDN上看见过的,可是当时竟然蒙了,忘记啦...

我承认自己是没有好好的用心去记住!

现在贴几个我做错的题目,不知道这样子会不会算是侵权,如果是,还请将本帖删除!!!!自己因为还是学生,这些方面还有些不明白...

2、下面代码有什么问题?为什么?

void foo(void)

{

char string[10],str1[10];

int i;

for( i = 0;i < 10; i++ )

{

str1[ i ] = 'a';

}

strcpy(string, str1);

printf( "%s", string);

}

我当时是这样子回答的,“没有字符串结束符,一直输出或者报错”,而书上提供的参考答案是这样子的:

“运行到strcpy的时候可能会产生内存异常”,其解释是:“因为str1没有结束标识符,str1数组后面继续存储可能不是'\0',而是乱码。printf函数,对于输出char* 类型,顺序打印字符串字符直到遇到空字符'\0'或者打印了由精度制定的字符数为止。”还好,也算是理解到了。

5、下面代码的结果是什么?为什么?

int main()

{

char a[1000];

int i;

for( i = 0; i < 1000; i++ )

a[i] = -1 - i;

printf( "%d",strlen( a ) );

return ( 0 );

}

我的回答是1000,因为内存一旦分配好了,其大小和具体地址不能再改变,除非重新动态分布。

书上提供的答案是这样子的,“255, 按照负数补码的规则,可以知道-1的补码是0xff,-2的补码为0xfe....当i的值为127时,a[127]的值为-128,而128是char类型数据能够表示的最小负数。当i继续增加,a[128]的值肯定不是-129.因为这是发生了溢出,-129需要9位才能够存储下来,而char类型数据只有8位,所以最高位被丢弃。剩下的8位是原来9位补码的低8位的值,即0x7f。当i继续增加到255时,-256的补码的低8位为0,当i继续增加到-256时,-257的补码低8位全为1,即低8位的补码为0xff,如此开始新一轮的循环…

按照上面的分析,a[0]~a[254]里面的值都不为0,而a[255]的值为0.strlen函数是计算字符串长度的,比不包含最后字符串的‘\0’,而判断一个字符串是否到达末尾的标志就是看是否遇见了‘\0’,如遇见则表示字符串结束。”

其实这个题目是看见过的,只不过当时就看看就过去了,可是再次做得时候却不知如何下手了,有点可恨。

7、下面两段代码有什么区别?什么时候需要用代码(2)?

代码(1)

int i = 10;

int j = i;

int k = i;

代码(2)

volatile int i = 10;

int j = i;

int k = i;

这个题目我当时是不会做的,就放弃了。主要是因为volatile没有接触过,就不熟悉了,直接看了答案,“代码1:这时候编译器对代码进行优化,因为在代码1的两条语句中,i没有被用作左值(就是没有被赋值)。这时候编译器认为i的只没有发生变化,所以在第一条语句从内存中取出i的值赋给j之后,这个值并没有被丢弃,而是在第二条语句继续赋给k。编译器不会产生汇编代码重新从内存里取i的值(不会编译生成装载内存的汇编指令,如ARM的LDM指令),这样子提高了效率。但要注意:两条语句之间i没有被用作左值才行。

代码2 :volatile关键字告诉编译器i的值随时可变,每次使用它的时候必须从内存中取出i的值,因此编译器会生成汇编指令重新从内存中取i的值。

代码2的使用时机:如果i是一个寄存器变量,表示一个端口数据或者是多个线程的共享数据,那么就容易出错,所以说volatile可以保证对特殊地址的稳定访问。”

这个确实挺不容易的,因为还没有接触多线程编程,可能还不是很理解,当时我想回用到的,因为接下来我会好好学习linux编程。当时上面的volatile确实用得很少,自己要注意下了。

8、在32位的X86系统下,输出的值为多少?

int main()

{

int a[5] = {1,2,3,4,5};

int *ptr1 = ( int *)( &a + 1);

int *ptr2 = ( int *)( (int)a + 1) ;

printf( “%x,%x”ptr1[-1],*ptr2 );

return ( 0 );

}

给的答案是5,2 000 000,具体是怎么样子的,也是关于指针的把,先放着,把后面总结完了再来查证。

9、0x01<<2+3的值是多少?为什么?

当时我的答案是,“不确定,移动的位数大于了要求移位的数,其结果是未定义的。”但是答案却给了当头一棒,结果是32,因为“+”的优先级高于<<,则先运算加法,在进行移位计算,这个和我的答案相差也太远了吧,不好!

后面的题目也差不多了,我想说的是,学了C大概两年了,可是现在连个80分得水平都没有,这个是有点可悲的呢,当时大学也差不多是这样的,引用几句我们学院牛人的话“老师教的恰好是我们不会用到的,而我们要用到的,确实他不教授的”…是有点可惜的。没关系,明年才工作,还有的机会补救。今天算是第一个步骤,恩!我会一直记录自己的成长历程的,为什么说是成长,因为我已经失败过了,这次一定会成功了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: