一、
int a,x;
for(a=0,x=0;a<=1 && !x++;)
{
a++;
}
printf("%d,%d/n",a,x);
结果:1,2
int a,x;
for(a=0,x=0;a<=1 && !x++;a++)
{
a++;
}
printf("%d,%d/n",a,x);
结果:2,1
这个题目中重点考察:
1.&&运算符,如果它左边为1,则右边需要计算;如果左边为0.则右边无需计算。
2.!x++的执行的是对x++表达式的!运算,因为!和++运算符具有相同的优先级,它们的结合性是从右向左运算,故++先于!运算。
二、
int a=2,x=2,p,q;
p = (a++)+(a++);
q = (++x)+(++x);
printf("%d,%d,%d,%d/n",a,x,p,q);
结果:4,4,4,8
说明:a++无论有多少项相加,都是各项先算完表达式,之后再自加1;
++x则是所有项先自加,之后再计算表达式。
三、
unsigned char a = 0xA5;
unsigned char b = ~a>>4;
b = b;
printf("b=%d/n",b);
结果:245,即11110101
说明:本题中如果不知道运算时编译器的自动类型转化,按照优先级的顺序,~高于>>,则得到结果是00000101,但是,由于在计算时,4默认为整型,故编译器先将a转化为000000A5后执行~运算,最后>>4,这样就能得到正确的结果。
四、
unsigned char a = 0xA5;
unsigned char b = a*2;
printf("b=%d/n",b);
结果:74
说明:本题考察b的存储范围是0-255,超过后高位会溢出,即165*2-256=74。
五、
float a = 1.0f;
int b = (int &)a;
int c = (int)a;
int *d = (int *)&a;
printf("%f,%d,%d,%d,%d,%f/n",a,b,c,d,*d,*d);
结果:1.000000,1065353216,1,1245052,1065353216,0.000000。
说明:
1.(int &)a把a强制转化为int型引用变量,从而b可以将a中的数据当作int型访问。但是由于浮点数的是以特定的形式在内存中存放,和整型数的排列方式不同,故输出1065353216。
2.d是一个指针,无论指针的基类型如何,32位系统总是用4个字节的宽度表示指针变量,可以通过类似(int *)a语句将指针的基类型进行转化,但是,指针的基类型只影响其的寻址和取值,寻址是指对其执行+,-运算时,实际移动的字节数;取值是指通过指针将处于某个地址的数据读出时,一次需要读出多少个字节,例如int *类型的指针只会读出4个字节。
六、
unsigned int a =0xFFFFFFF7;
unsigned char i = (unsigned char)a;
char *b = (char *)&a;
printf("%08X,%08X/n",i,*b);
结果:000000F7,FFFFFFF7
说明:printf语句的%X格式表示输出16进制数,且将输入参数提升为整型,即对char数据进行符号扩展,无符号数就是0扩展,有符号数如果最高位是1的话,则进行1扩展,否则0扩展,故b将被执行了符号扩展。printf语句会按照既定的格式,如%x,%d,%u等格式将输入参数输出,但是如果输入参数不符合默认的输入条件,printf语句会按照自动转换规则对其转换后输出。
引用:
If the expression_r_r_r_r that denotes the called function has a type that does not include a
prototype, the integer promotions are performed on each argument, and arguments that
have type float are promoted to double. These are called the default argument
promotions.
七、
int b = 3;
int arr[] = {6,7,8,9,10};
int *ptr = arr;
*(ptr++)+=123;
printf("%d,%d",*ptr,*(++ptr));
结果:8,8
int b = 3;
int arr[] = {6,7,8,9,10};
int *ptr = arr;
*(ptr++)+=123;
printf("%d,%d",*ptr,*ptr++);
结果:7,7
说明:1.printf语句的计算顺序是自右向左,所以才有例1的结果。
2.++运算符和*运算符具有相同优先级,但结合性是自右向左,故例2中先算ptr++后算*,由于++在变量后时,总是整个表达式计算完之后才将变量加1,故printf执行完之后,才将ptr加1,所以才有例2的结果。
八、
printf("%f/n",5);
printf("%f/n",5.0);
结果:程序崩溃、5.000000
说明:printf待%f时,默认从堆栈中取出8个字节的数,并将其作为浮点数输出,故第一个printf语句会出现内存访问越界错误。printf和scanf函数的平台依赖性很强,使用时,%f后面必须要跟浮点数或指向浮点数的指针,否则会发生难以预料的错误,printf函数有自动扩展的规则。
九、
Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;
以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;
第一个扩展为
struct s * p1, p2;
上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。
十、
int a[2][2][3];
for(int i = 0;i <12;i++)
printf("%d",a[x][y][z]);
问x=?y=?z=?
三个维大小 I = 2,J = 2,K = 3
x,y,z
i = 0, 0,0,0
i = 1, 0,0,1
i = 2, 0,0,2
i = 3, 0,1,0 <-- 进位
i = 4, 0,1,1
i = 5, 0,1,2
i = 6, 1,0,0 <-- 进位
i = 7, 1,0,1
i = 8, 1,0,2
i = 9, 1,1,0 <-- 进位
i =10, 1,1,1
i =11, 1,1,2
分析:z比较简单,直接模3即可在0,1,2之间循环;y需要先将i变成0,1,2,3,即i/3即可,之后模2;
而x没有循环变化,故不需要模运算,只要将x变成0,1即可,故i/6。
故结果应该为:printf("%d",a[i/(2*3)][(i/3)%2][i%3]);