本文共 2629 字,大约阅读时间需要 8 分钟。
分析如下程序的输出:
void fun(int m, int n){ printf("m = %d, n = %d\n", m, n);}int main(void){ int k = 3; fun(k += 3, ++k); printf("k = %d", k); return 0;}
主要考察是调用函数的时候参数的入栈顺序以及变量的运算,参数入栈顺序一般是从右到左,所以先执行++k,将4传给n;再执行k += 3将7的值传给m。注意这里是k做运算之后才传入的函数,所以k += 3, ++k并不是在调用函数的栈中执行的,所以k的值是保存下来的,所以最终输出为:
m = 7, n = 4
k = 7
这种方式和编译器中得函数调用关系相关即先后入栈顺序。不过不同编译器得处理不同。也是因为 C 标准中对这种方式说明为未定义,所以各个编译器厂商都有自己得理解,所以最后产生得结果完全不同。因为这样,所以遇见这种函数,我们首先要考虑我们得编译器会如何处理这样得函数,其次看函数得调用方式,不同得调用方式,可能产生不同得结果。最后是看编译器优化。
分析下面程序:
#includevoid fun(int b[][3]){ ++b; b[1][1] = 120;}int main(void){ int a[][3] = { { 1, 2, 3}, { 4, 5, 6}, { 7, 8, 9} }; fun(a); printf("a[2][1] = %d\n", a[2][1]); return 0;}
首先要了解数组传入函数后的变化**:我们知道数组传入函数的时候,会转换为指针,但是对于二维数组,只转换一次**,即int b[][3]
传入函数的时候是以
int (*b)[3]
的形式,即一个指向数组的指针,数组中有三个元素。所以传入a后,相当于b = a[0]
。
++b
代表指针b移动一个步长的位置,这里b指向一个三个元素的int型数组,所以++b
之后b = a[1][]
。
指向b[1][1] = 120
, 其中b[1][1]
相当于*(*(b+1)+1)
,相当于指针b偏移了一个步长之后又偏移了一个元素的位置,用a表示a[1+1][0+1]
即a[2][1] = 120
,所以printf输出的就是120。
用一段程序说明:
#include#define A#define Bvoid test(int a,int b){ }int main(void){ #if 0 #ifdef A&&B test(printf("a\n"),printf("b\n"));#endif#endif#if defined(A)&&defined(B) test(printf("a\n"),printf("b\n"));#endif return 0;}
如果是#if defined(A)&&defined(B)
的形式,输出:
b
a
如果是#ifdef A&&B
的形式,会提示:
因为#ifdef虽然我们最常见也用得最多,可是#if defined(XXX)却可以有 &&,||,!,逻辑与,逻辑或,逻辑非等操作,而#ifdef却不支持这样的特性。
程序如下:
void swap(int *a, int *b){ *a = *a + *b; *b = *a - *b; *a = *a - *b;}
请问上述程序可否实现两个int数据的交换?看起来没毛病,可是容易忽略一个问题,那就是int是有符号数据的溢出!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nwq6O0su-1602905143136)(…/…/…/%E8%BD%AF%E4%BB%B6%E7%AE%A1%E5%AE%B6/Typora/%E5%9B%BE%E7%89%87%E5%BA%93/image-20201017103737242.png)]
**只有当a、b同符号的时候才可能发送溢出!!!**因为这里有加减操作,所以当两个同符号的数据相加的时候就有可能溢出。
比如:
交换-5, -7。 以4bit为例。
-5 = 1011 (补码) -7 = 1001 (补码)
(-5)+ (-7)= 10100=0100=4 (溢出后为4)
4-(-7)= 4 +7=0100 + 0111 = 1011 = -5的补码
4-(-5)= 4 + 5 = 0100 + 0101 = 1001 = -7的补码
注意,函数是在第一步的时候可能溢出,但是后面的操作是基于溢出的数据的,而且后面又可以把溢出的部分减回来,所以这里虽然可能会发送溢出,但是仍然可以得到正确的数据。
程序如下:
#includevoid test(){ printf("int: %d\n", sizeof(int)); printf("double: %d\n", sizeof(double)); printf("test1: %d\n", sizeof(100 < 1 ? 0.1 : 1)); printf("test2: %d\n", sizeof(100 > 1 ? 0.1 : 1));}int main(void){ test(); return 0;}
输出结果为:
int: 4double: 8test1: 8test2: 8
如果按照我们分析,(100 < 1 ? 0.1 : 1)
输出的会是1,也就是int型数据,但是实际上被转换为double类型了。
实际上三目运算最后输出的是一个变量,在一个表达式中,数据格式要统一,所以在得出运算之前就将所有变量转换为同一种数据格式了。
转载地址:http://ytwzi.baihongyu.com/