dui
回复 6楼 gxhzzhj
要说明这个问题,得了解一下参数的传递方法。32769 这个数,写成二进制是这样的:
0000 0000 0000 0000 1000 0000 0000 0001
为了方便,把它写成16进制,那么是这样:
0 0 0 0 8 0 0 1
按字节就是:
00 00 80 01
程序在运行到printf时,由main负责求出参数的值,并将之压入栈中,以便被调函数使用。
在intel兼容机里,内存都是使用一种叫做 little endian(中文有好多叫法,低位低址呀,小端在前之类的,我也不清楚)的方式储存的。把低位的数放在低地址,就是低位在前的意思。所以那个数压入堆栈之后,就会变成下面这个顺序:01 80 00 00。
本来参数传递有按照从左到右的顺序,还是从双到左的顺序标准是没有规定的(虽然大多数的实现都是从右到左的顺序压栈)。好在这个程序前后传的两个参数值一样,所以这个顺序不影响结果。main函数负责传递两个参数,它们压入堆栈之后,栈中的数据就是下面这个样子:
01 80 00 00, 01 80 00 00 (为了方便阅读,我加了个逗号。)
之后调用了printf,它也不知道传的参数是什么类型,只好看格式串中相应的类型描述符。
再这里,你先后写的是 %d 和 %ld
在TC中,int 是2个字节的,所在printf在看了%d 后,从栈中读了两个字节: 01 80,然后解译成 int 的值输出。
01 80 是 little endian 的顺序,所以是80 01,这个数就是 -32767。
接着,printf 又看见了 %ld。就是 long,四个字节的,所以又去读了4个字节:00 00 01 80 (其实从这就可以看出来,传的参数已经乱套了,这四个字节数是第一个参数的后两个字节,和第二个参数前两个。跨越了我上面加的逗号)
这是 little endian 的。所以其实是:80 01 00 00, 这个数是 -2147418112。
你可以自己写个例子试试看,比如:
程序代码:
#include <stdio.h> int main(void) { int a = 0x8001; long b = 0x80010000; printf("%d, %ld\n", a, b); return 0; }
看看结果是不是一样的。
顺便解译一下,不同的编译器编译的结果也不一定是一样的。TC中的 int 是2个字节的,相当于 short。其它很多编译中的 int 都是4个字节,相当于 long。在这种情况下,传 int 和传 long 是没有什么区别的,也就不会出现你说的这个问题了。