user-0 提问: C语言题目，为什么这样？

回复:
user: user-1
content: 引用 29 楼 gblhack 的回复:容易迷惑的地方可能是short i = -4，在内存中是FF FC ，我们用%d就是输出的 FF FC ，其实%d输出的是“i”这个表达式的结果，而不是其在内存中存放的值。 这里更正一下: short i  =-4； printf("%d  %o  %x  %u",i,i,i,i);  并不是说把short型的参数i转换成%d对应的int，而是C语言对此有约定，如fefe82老师所说的 引用short 类型的变量 i 用于 printf(format, ...) 后面 ... 部分的参数，会经历 integer promotion 也就是说i被转换成int型和%d %o %x %u占位符无关，而是C语言规定函数中未进行类型说明的参数，在传参时会对实参进行Default Argument Promotion（缺省参数提升）。default argument promotion包括fefe82老师说的integer promotion和一个float转换成double(相对于printf函数，其他的不清楚)。 而我前面说的“其实%d输出的是“i”这个表达式的结果，而不是其在内存中存放的值” 是错误的，%d就是以int型读取i的“内存”，这里仅用内存来说可能也不太准确，因为这涉及到一个栈的概念，但我还没有学习到，所以就不和你多说了，以免对你再次误导。 至于“%d就是以int型读取i的“内存”的证明：printf("%d  %d",1.0,(int)1.0); %d输出(int)1.0结果为1，%d输出1.0结果为0。 参考资料http://www.zhihu.com/question/28467596  http://blog.csdn.net/astrotycoon/article/details/8284501 最后可能需要再说明一点，由于我也是一个C语言初学者，所以我的所有回复并非专业问答，而是报着学习交流的态度与同样的初学者共同探讨，如果我的观点对你产生了误导，我对此十分抱歉。

user: user-2

user: user-3
content: 电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

user: user-4
content: 要限定IA32，也能做。。 啥也不限定，是单片机 还是ia32 还是64.。。 就写个 main。。

user: user-4
content: 。。又是谭浩强的 掉书袋的 题 么。。

user: user-5
content: printf 在传递参数时，对于 char、short、int 都提升到了 int 类型，相当于有个隐式转换。转换后的结果取决于编译器位数，这跟你前面用的是 short 还是 char 还是 int 没关系，结果都是一样的。如果是 16 位的编译器，int 通常也是 16 位，转换之后也是 16 位整数。32 位的编译器，int 通常也是 32 位，转换之后也是 32 位整数。用计算器以 16 位和 32 位分别对照 -4 在不同进制下的值就明白了。

user: user-6
content: 可能和系统内存有关，目前正在学习

user: user-1
content: 引用 30 楼 qq_33417622 的回复:非常感谢啊！！！谢谢谢谢！ 相互学习

user: user-7
content: 试了一下，32位系统得到的结果是：-4    177774    ffc   fffffffc  64位系统没试。

user: user-8
content: 对的,非常正确

user: user-9
content: 跟系统最大取值范围有关，楼主别纠结这个问题了 书上肯定都老爷机了 换本书看吧  那本太老了

user: user-10
content: 计算机位数问题，16位与32位是有区别的

user: user-3
content: 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！

user: user-0
content: 引用 29 楼 _郭的回复:[quote=引用 11 楼 qq_33417622 的回复:] [quote=引用 7 楼 _郭的回复:]这个问题很简单，第一你要sizeof(int)看一下占用几个字节，然后确定-4在内存中的存放形式。 我这里假设int占用4个字节，那么-4在内存中 ： 1111 1111 1111 1111 1111 1111 1111 1100    (至于为什么是这样存放的请参看一下有符号整数在内存中的存放形式) 用16进制输出这个2进制数就是 FFFFFFFC 8进制输出： 37777777774 10进制输出： 4294967292 至于你怎么笔算的，没说过程不知道你错在哪里，但肯定是错的。 另外你可以参考：   unsigned int n =0xFFFFFFFF;   printf("%d",n); 变量n的类型决定它怎么存放，而%d决定以什么方式读取n的这块内存。 我用sizeof测试，short占用两个字节的。也就是16位。[/quote]  只注意到了有符号到无符号的转换，没注意到short到int的转换，这位老师说的很清楚，你可以看一下  引用 8 楼 fefe82 的回复:2) short 类型的变量 i 用于 printf(format, ...) 后面 ... 部分的参数，会经历 integer promotion 。   经过 integer promotion ，它会被转换为 int （如果 sizeof(short) < sizeof(int)）或 unsigned int （如果 sizeof(short) == sizeof(int)）。 3) 在以上情况下，如果一个小于零的 short i 转换为 int ，其值不变。否则(即被转换为了 unsigned int)，其值变为 UINT_MAX + 1 + i (请按数学中的基本运算规则计算这个值，而不是按 C 语言中的表达式计算规则）   其中，UINT_MAX 是 unsigned int 所能表示的最大的值。由于 sizeof(int) 是依赖于编译器的，UINT_MAX 也是  ———————————————————————————————————————————— 便于理解我做一个测试： 断下单步执行后，先看一下局部变量窗口i的值(数组的地址)，然后再内存窗口跳转到该地址，可以看到数组i在内存中存放的形式 (16进制显示的)。  至于为什么要用数组和为什么要解释这一步，是因为看到上面有人说什么把它后面的数据也输出了，故验证一下。  下面验证fefe82老师说的short转换成int：  我们可以看到short转换成int确实会经历integer promotion(整型提升)，也就是说我们把i[1]赋值给变量ii并不只是简单的内存拷贝。 我简单说一下我理解的转换过程：  int ii = i[1]; 首先int ii，编译器会为ii分配4个字节的内存地址，然后再根据“=”号右边的表达式的结果初始化； "="号右边是i[1]，编译器首先会取出它的值，得出结果 -4，然后用-4初始化变量ii； 把 -4 存储在ii的内存空间。 ———————————————————————————————————————————————— 而你的实验用%d %o 等输出short i，相当于： printf("%d  %o  %x  %u",-4,-4,-4,-4); 容易迷惑的地方可能是short i = -4，在内存中是FF FC ，我们用%d就是输出的 FF FC ，其实%d输出的是“i”这个表达式的结果，而不是其在内存中存放的值。 __________________________________________________________________________________ 最后再感谢一下fefe82老师，另外同学其实不必过于纠结存储方式和占用多少字节什么的，了解就可以了。[/quote] 非常感谢啊！！！谢谢谢谢！

user: user-11
content: GP论坛没落了，这样就能留人？

user: user-12
content: 不同的编译环境导致分配的存储字节大小有差异，有的分配2个字节有的是4个字节。

user: user-1
content: 引用 11 楼 qq_33417622 的回复:[quote=引用 7 楼 _郭的回复:]这个问题很简单，第一你要sizeof(int)看一下占用几个字节，然后确定-4在内存中的存放形式。 我这里假设int占用4个字节，那么-4在内存中 ： 1111 1111 1111 1111 1111 1111 1111 1100    (至于为什么是这样存放的请参看一下有符号整数在内存中的存放形式) 用16进制输出这个2进制数就是 FFFFFFFC 8进制输出： 37777777774 10进制输出： 4294967292 至于你怎么笔算的，没说过程不知道你错在哪里，但肯定是错的。 另外你可以参考：   unsigned int n =0xFFFFFFFF;   printf("%d",n); 变量n的类型决定它怎么存放，而%d决定以什么方式读取n的这块内存。 我用sizeof测试，short占用两个字节的。也就是16位。[/quote]  只注意到了有符号到无符号的转换，没注意到short到int的转换，这位老师说的很清楚，你可以看一下  引用 8 楼 fefe82 的回复:2) short 类型的变量 i 用于 printf(format, ...) 后面 ... 部分的参数，会经历 integer promotion 。   经过 integer promotion ，它会被转换为 int （如果 sizeof(short) < sizeof(int)）或 unsigned int （如果 sizeof(short) == sizeof(int)）。 3) 在以上情况下，如果一个小于零的 short i 转换为 int ，其值不变。否则(即被转换为了 unsigned int)，其值变为 UINT_MAX + 1 + i (请按数学中的基本运算规则计算这个值，而不是按 C 语言中的表达式计算规则）   其中，UINT_MAX 是 unsigned int 所能表示的最大的值。由于 sizeof(int) 是依赖于编译器的，UINT_MAX 也是  ———————————————————————————————————————————— 便于理解我做一个测试： 断下单步执行后，先看一下局部变量窗口i的值(数组的地址)，然后再内存窗口跳转到该地址，可以看到数组i在内存中存放的形式 (16进制显示的)。  至于为什么要用数组和为什么要解释这一步，是因为看到上面有人说什么把它后面的数据也输出了，故验证一下。  下面验证fefe82老师说的short转换成int：  我们可以看到short转换成int确实会经历integer promotion(整型提升)，也就是说我们把i[1]赋值给变量ii并不只是简单的内存拷贝。 我简单说一下我理解的转换过程：  int ii = i[1]; 首先int ii，编译器会为ii分配4个字节的内存地址，然后再根据“=”号右边的表达式的结果初始化； "="号右边是i[1]，编译器首先会取出它的值，得出结果 -4，然后用-4初始化变量ii； 把 -4 存储在ii的内存空间。 ———————————————————————————————————————————————— 而你的实验用%d %o 等输出short i，相当于： printf("%d  %o  %x  %u",-4,-4,-4,-4); 容易迷惑的地方可能是short i = -4，在内存中是FF FC ，我们用%d就是输出的 FF FC ，其实%d输出的是“i”这个表达式的结果，而不是其在内存中存放的值。 __________________________________________________________________________________ 最后再感谢一下fefe82老师，另外同学其实不必过于纠结存储方式和占用多少字节什么的，了解就可以了。

user: user-13
content: 我用64位的运行了一下 结果分别是 -4  37777777774    fffffffc   4294967292

user: user-0
content: 引用 22 楼 user-14的回复:跟你的编译环境有关啊，16位跟32位数据肯定不相同啊，负数首位是1，后面跟的0差好多，位数不同转换后的数差十万八千里啊 你看看我的解释，编译环境不同，你看看楼上我的思考

user: user-14
content: 跟你的编译环境有关啊，16位跟32位数据肯定不相同啊，负数首位是1，后面跟的0差好多，位数不同转换后的数差十万八千里啊