今天看到某人列出了几十个C语言迷题,很有意思。顺手做了一下,发现其实大多数都是来自C Faq,Expert C Programming,和网上出现的一些C语言技巧,一些很好,连我自己都被难住了,一些却又狠简单狠基础。除了第8个和第26个需要进一步理解,剩下的我全都作了简单的解答,不明白的请留言提问。
题目在这里:http://www.gowrikumar.com/c/
我的解答如下:
1. 见ECP第29页,一模一样的例子。
2. OS_HP-UX_print这不是一个有效的名字。//blush 一开始我也没注意到!
3. do-while的常识,你应该知道continue到哪里。如果不知道,看看C99第6.8.6.2节。
4. 常见问题,因为stdout是带缓冲的,如果不换行的话,是会有问题的!
5. h会被展开,而g不会。见C-FAQ,Question 11.17。
6. case后面的是字符,不是整数。
7. IA-64是RISC,不能访问未对齐的地址。
8. 感觉没错,但还未发掘出其原理。。。
9. 直接比较浮点数被认为是有害的,说过多次了。
10. 常识。如果很喜欢在初始化时用逗号运算符来标新立异,请加括号!
11. 当然合法!谁还以为printf是void类型?!它返回的是成功输出字符的个数!
12. duff’s device,是用Tom Duff的名字来命名的。很有名的一个东西,用来优化拷贝的,据说和Rob Pike此牛还有点儿关系~!不过注意,原始的duff’s device中的to可是不变的,因为它指向一个映射到内存的寄存器。
13. 正确,逻辑很简单,每次都保留除最低位置的1之外的1,减去1,依次测试。
14. 说过N^2次了,int foo()和int foo(void)是不一样滴!
15. 第二个是把a的内存比特位模式用int来解释。
第一个比较有意思,因为类型不匹配,而且float在被压入压出的过程中会被扩展精度,因为IA-32的浮点数寄存器都是80bits的。所以,float会被扩展成double后再当int处理!!
16. 声明的问题,指针不是数组。
17. switch嘛,当然会跳过第一个case/default之前的东西,所以初始化就被跳过了。
18. 切,形参写得再好数组也得退化啊!
19. format string overflow?!
20. C99 第7.19.6.2节,第5条。
21. buffer overflow
22. sizeof是操作符,编译时决定的,而非运行时。
23. ECP,第25页。
24. 等号优先级高于逗号。
25. 减法和除法错误,减数和被减数反了,除法同理。
26. 蛮牛的一段代码,还没看出其中的奥妙。以后看懂会另行说明。;-)
27. 以0开头是8进制,而最后一个是十进制。
28. scanf返回成功输入的个数。
29. /和*会被当成注释处理,所以那一行实际上是y=y;
30. -也要被输入。
31. &n
32. 加号优先级高于左移。
33. 当然不合法,return不能出现在表达式中。
34. 把for括号里的最后一个i换成n。暂时就想到这一个解法。
35. 显然ptr2不是指针。
36. 错误!因为会被0除!
37. 很明显是8。
38. free的地址不对。
39. 很简单,就是把a[n]换成了n[a],本质上一样。
40. 字符a前面的所有,见C99 7.19.6.2.12。
41. 一个是定义,其余是声明。
42. 取某个成员在其结构体中的偏移。
43. 就是宏的常见错误,比如:SWAP(a++, ++b)。
44. 某个表达式及其对应的值。
45. 参见Python源代码,Objects/intobject.c::int_add。
46. n/x向上圆整!
47. c会被自加两次。
48. 不能一个参数都没有就使用“…”。
49. 用?:三元操作符。;-)
50. 把输出字符的个数存入某个变量中,见过。
51. -_-b
52. %%
53. 后一个指针只读,前一个指针指的东西只读。
54. 前者不能重叠,后者可以。
55. %lf, %f, %g。就记起来这仨。
56. 写过N遍了。。。
57. 厄,看我这个:
#include <stdio.h>
int main(void)
{while(printf(“Hello World!”)<0){}}
4. 常见问题,因为stdout是带缓冲的,如果不换行的话,是会有问题的!
请问:这里的缓冲应该怎么理解?
这个buffer是由语言提供的,还是操作系统提供的?是不是每个操作系统都有stdout,stdin和stderr?我一直怀疑win 没有stderr这东西,它在console里都是通过Debug来输出的完成的。
[Reply]
To Kermit:是由FILE结构体提供的。Linux和Unix都有,标准规定也要有,至于window$有没有,别问俺!俺也不想知道~!
BTW,能不能别提win???
[Reply]
1. 缓冲 IO 是 stdio lib 的标准功能,也有不缓冲的函数调用,可以设置缓冲的大小。
2. 这是 C 的标准库,因此 Windows 上如果遵从 C 的运行库标准,必须提供。
[Reply]
RE:BTW,能不能别提win???
好。(怕你了-_-!)
[Reply]
看了下第8个题,应该是分组求和的过程。跟矢量计算机加法算法类似。
对32位的unsigned int x 来说:
首先:将x每1位看作一组,分为32组,每组中相应位本身的值就是该组“1”的个数。这32个值加起来就是要求的答案。
for循环中:
第一轮:把x每相邻两组合并为一组,变成16组,即将x每相邻两组加在一起。这样每组的值就是就是原来相应位置的两小组之和,则这16个值加起来仍是答案。
第二轮:分为8组
……
第五轮:成为1组,得出答案。
这个算法真好,谢谢分享~
[Reply]
感谢楼上的解释!明白了,谢谢~!
[Reply]
第六题你肯定没听作者的话,去运行一下。
实际上是defa1ut写错了。
而且字符1,2和10也不相等。
[Reply]
你说的第2点我已经指出了。关于default,那是作者故意欺骗,无聊的把戏,你认为实际中vim/emacs不认得么?
[Reply]
19. format string overflow?!
请问连个int的空间都没有了怎么还能传那么长的字符串?不是“?!”是“!!”:)
34. 把for括号里的最后一个i换成n。暂时就想到这一个解法。
-i<n
i+n
[Reply]
6. case后面的是字符,不是整数。
这个不对,是因为源码中的default拼得不对(代码中是”defa1ut”)
[Reply]
kongove reply on July 9, 2008 9:23 am:
to jtkk:
要是把default拼成”defau1t”那才绝呢~
defau1t在这里被识别成了普通的标签~
[Reply]