#include int main() { int i,n; int a = 123456789; void *v = &a; unsigned char *c = (unsigned char*)v; for(i=0;i< sizeof a;i++) { printf("%u ",*(c+i)); } char *cc = (char*)v; printf("n %d", *(cc+1)); char *ccc = (char*)v; printf("n %u n", *(ccc+1)); }
该程序在我的32位Ubuntu机器上生成以下输出。
21 205 91 7 -51 4294967245
前两行输出我能理解=>
请解释最后一行输出。 为什么添加三个1的字节因为(11111111111111111111111111001101) = 4294967245
。
显然你的编译器使用有符号字符,它是一个小端,二进制补码系统。
123456789d = 075BCD15h Little endian: 15 CD 5B 07
因此v + 1给出值0xCD
。 当它存储在signed char中时,您将获得带符号十进制格式的-51
。
当传递给printf时,包含值-51
的字符*(ccc+1)
首先被隐式类型提升为int
,因为像printf这样的可变参数函数有一条规则,声明所有小整数参数都会被提升为int
( 默认参数提升 ) 。 在此促销期间,标志将被保留。 您仍然具有值-51,但对于32位有符号整数,它给出值0xFFFFFFCD
。
最后, %u
说明符告诉printf将其视为无符号整数,因此最终得到4.29 bil。
这里要理解的重要部分是%u
与实际类型提升无关,它只是告诉printf如何在促销后解释数据。
-51
以8位hex存储为0xCD
。 (假设2s称赞二进制系统)
当你将它传递给像printf
这样的可变函数时 ,会发生默认参数提升,并使用表示forms0xFFFFFFCD
(对于4字节int)将char
提升为int
。
解释为int
0xFFFFFFCD
是-51
并解释为unsigned int
是4294967245
。
进一步阅读: C函数调用中的默认参数提升
请解释最后一行输出。 为什么添加三个1的字节
这称为符号扩展 。 当较小的有符号数被分配(转换)为较大的数字时,其符号位被复制以确保它代表相同的数字(例如1s和2s补码 )。
错误的printf
格式说明符
您正在尝试使用指定unsigned [int]
"%u"
打印一个char
,指定unsigned [int]
。 与printf
中的转换说明符不匹配的参数是7.19.6.1第9段中的未定义行为。
如果转换规范无效,则行为未定义。 如果任何参数不是相应转换规范的正确类型,则行为未定义。
使用char
来存储签名值
另外,为了确保char
包含有signed
值,显式使用signed char
作为char
可以表现为signed char
或unsigned char
。 (在后一种情况下,您的代码段的输出可能是205 205
)。 在gcc
您可以使用-funsigned-char
选项强制char
表现为unsigned char
。
以上就是c/c++开发分享使用%u读取签名的字符相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/562176.html