其实已经看了很多很好的帖子,但是只看帖子不能达到系统的认识/最新的认识,一定要看官方标准/大牛著作!
值得深究的有:4
1、下面的程序并不见得会输出 hello-std-out 在Qt 5.2 Plain C Project下测试,每次都会输出hello-std-out。
参考答案:stdout是块设备,stderr则不是。对于块设备,只有遇到下面几种情况下才会被输入,1)遇到回车,2)缓冲区满,3)flush被调用。#include <stdio.h> #include <unistd.h> int main(void) { while(1) { fprintf(stderr,"hello-std-err "); fprintf(stdout,"hello-std-out "); sleep(1); } return 0; }
2、下面的程序看起来是正常的,使用了一个逗号表达式来做初始化。
参考答案:这个程序会得到编译出错(语法出错),逗号表达式是没错。 但是在初始化和变量声明时,逗号并不是逗号表达式的意义。这点要区分,要修改上面这个程序,需要加上括号: int a = (1,2);#include <stdio.h> int main() { int a = 1,2; printf("a : %d\n",a); return 0; }
3、下面的程序会有什么样的输出
运行结果:#include <stdio.h> int main() { int i=43; printf("%d\n",printf("%d",printf("%d",i))); return 0; }
参考答案:printf返回值是输出的字符个数。
4、下面的程序会输出什么 这个值得重点分析,涉及到计算机内部存储数据的格式,需要补补计算机系统结构了
#include <stdio.h> int main() { float a = 12.5; printf("%d\n", a); printf("%d\n", (int)a); printf("%d\n", *(int *)&a); return 0; }
运行结果:
参考答案:浮点数是4个字节,12.5f 转成
二进制是:01000001010010000000000000000000,
十六进制是:0x41480000,
十进制 是:1095237632。
所以,第二和第三个输出相信大家也知道是为什么了。而对于第一个,为什么会输出0,我们需要了解一下float和double 的内存布局,如下:
float: 1位符号位(s)、8位指数(e),23位尾数(m,共32位)
double: 1位符号位(s)、11位指数(e),52位尾数(m,共64位)然后,我们还需要了解一下printf由于类型不匹配,所以,会把float直接转成double,注意,12.5的float和double的内存二进制完全不一样。别忘了在x86芯片下使用是的反字节序,高位字节和低位字位要反过来。所以:
float版:0x41480000 (在内存中是:00 00 48 41)
double版:0x4029000000000000 (在内存中是:00 00 00 00 00 00 29 40)
而我们的%d要求是一个4字节的int,对于double的内存布局,我们可以看到前四个字节是00,所以输出自然是0了。 这个示例向我们说明printf并不是类型安全的,这就是为什么C++要引如cout的原因了。
5、下面,我们再来看一个交叉编译的事情,下面的两个文件可以编译通过吗?如果可以通过,结果是什么
file1.c
file2.cint arr[80];
Visual Studio 2010 编译错误提示:extern int *arr; int main() { arr[1] = 100; printf("%d\n", arr[1]); return 0; }
参考答案:一个指向数组的指针,并不等于一个数组。修改:extern int arr[]。(参考:ISO C语言 6.5.4.2 节)
6、是关于switch语句的,参见博文:switch的三个注意点
7、请问下面的程序会有什么潜在的危险
记得刚学C语言时,字符串以‘\0’结束这个知识点被我忽略了很久,也因此让我有点时间遇到类似问题,痛苦的要死。#include <stdio.h> int main() { char str[80]; printf("Enter the string:"); scanf("%s",str); printf("You entered:%s\n",str); return 0; }
参考答案:本题很简单了。这个程序的潜在问题是,如果用户输入了超过80个长度的字符,那么就会有数组越界的问题了,你的程序很有可以及会crash了。
8、请问下面的程序输出什么
运行结果:Tested by Qt Plain C Project#include <stdio.h> int main() { int i; i = 10; printf("i : %d\n",i); printf("sizeof(i++) is: %d\n",sizeof(i++)); printf("i : %d\n",i); return 0; }
参考分析:sizeof不是一个函 数,是一个操作符。求(i++)的类型的size,这是一件可以在程序运行前(编译时)完全的事情,所以,sizeof(i++)直接就被4给取代了,在运行时也就不会有了i++这个表达式。
9、请问下面的程序的输出值是什么#include <stdio.h> #include <stdlib.h> #define SIZEOF(arr) (sizeof(arr)/sizeof(arr[0])) // 我愚昧了,以前从来没想过用这种方式计算定义时未指定 // 数组长度的数字的长度 #define PrintInt(expr) printf("%s:%d\n",#expr,(expr)) // #expr以字符形式输出expr int main() { int pot[] = { 0001, 0010, 0100, 1000 }; int i; for(i=0;i<SIZEOF(pot);i++) { PrintInt(pot[i]); } return 0; }
运行结果:
参考答案:其实很简单,在C/C++中,以0开头的数字都是八进制的。
10、下面的输出是什么
运行结果:#include <stdio.h> int main() { int i = 6; if( ((++i < 7) && ( i++/6)) || (++i <= 9)); printf("%d\n",i); return 0; }
参考答案:本题主要考的是&&和||的短路求值的问题。
11、下面的C程序是合法的吗?如果是,那么输出是什么
运行结果:#include <stdio.h> int main() { int a=3, b = 5; printf(&a["Ya!Hello! how is this? %s\n"], &b["junk/super"]); printf(&a["WHAT%c%c%c %c%c %c !\n"], 1["this"],2["beauty"],0["tool"],0["is"],3["sensitive"],4["CCCCCC"]); return 0; }
参考答案:下面的两种用法是相同的: "hello"[2], 2["hello"]。如果你知道:a[i] 其实就是 *(a+i)也就是 *(i+a),所以如果写成 i[a] 应该也不难理解了。
12、请问下面的程序输出什么
运行结果-1:#include <stdio.h> int main() { char dummy[80]; printf("Enter a string:\n"); scanf("%[^r]",dummy); printf("%s\n",dummy); return 0; }
运行结果-2:
参考答案:"%[^r]",当且仅当遇到字符r才结束输入,而且r不被指针接收。
13、下面的程序试图使用“位操作”来完成“乘5”的操作
int FiveTimes(int a) { int t; t = a<<2 + a; // 因为<<的优先级低于+,所以正确的是:t = (a<<2) + a; return t; }