20230418CodeBlocks17.12下相同语句打印结果不同


一、出现问题

#include  <stdio.h>
typedef struct {    
   char cBitL : 4,
   		cBitH : 4; 
} charBit; 
int main() {  
   charBit test;  
   test.cBitL = 0x1;  
   test.cBitH = 0x4;
   printf("charBit size is %u\n", sizeof(test));  // 打印1号
   printf("charBit test castInt is %d\n", test);  // 打印2号  
   printf("charBit test castChar is %c\n", test);
   printf("charBit test is 0x%x\n", test);    
   return 0;
}

在CodeBlocks17.12下编译运行结果如下

charBit size is 1
charBit test castInt is 65
charBit test castChar is A
charBit test is 0x41

将代码中打印1号行注释掉后运行结果如下

charBit test castInt is 4200769
charBit test castChar is A
charBit test is 0x401941

两者打印结果不同

二、分析问题

1、第一轮打印

第二个打印语句使用了错误的格式化符号来输出charBit类型的test变量,因此输出的结果为test变量的ASCII码值。这里假设代码被编译在ASCII编码环境下。

charBit结构体定义中,cBitL和cBitH分别为4位的位域,共占据了1个字节(8位)的存储空间。在这里设置test变量的cBitL为0x1,cBitH为0x4
因此在ASCII码环境下,test变量的值可以表示为二进制0001 0100,即16进制的0x14,而0x14的ASCII码值为65。

因此,当直接使用错误的格式化符号"%d"时,输出的结果是65。

2、第二轮打印

在charBit结构体中,cBitL和cBitH都只占用了4个bit位,将cBitL的值设置为0x1,即二进制001,将cBitH的值设置为0x4,即二进制0100
当这两个位域合并为一个字节时,其对应的二进制值为00010100
即16进制数0x14,而0x14对应的ASCII值为’\x14’或者20

十进制数值 20 的 ASCII 码值为 0x14(16进制)
65对应的ASCII码值为 0x41(16进制)
当将这两个ASCII码值相加时,会得到十进制数值 85(0x55,16进制)

在最初的代码中,程序使用了错误的格式化标识符 “%d” 对 test 变量进行格式化输出。因此,当程序运行时,printf函数将 test 变量的内存地址视为一个指向int类型的指针,并将其解释为一个整数类型的值进行输出。由于在不同编译器和平台情况下,整型数值的字节顺序可能不同,因此具体输出结果会有所不同。在这个特定的情况下,变量 test 的二进制值为 00010100(16进制 0x14),而将其解释为一个无符号整数类型时,这个二进制值被视为所表示的十进制数值 335544320 (16进制 0x14000000)。

进一步地,当将上述的十进制数值 85(0x55,16进制)与 335544320 相加时,会得到无符号整数值 4200769。这个值是中间过程中格式化输出错误、再将test变量的内存视为int类型指针进行无意义转换的结果

在VS下时,则不会出现这种情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值