C语言程序输出异常 实际打印SNW与预期值SNP不符问题咨询
C程序输出"SNP"与预期不符问题排查
问题现象
- 程序预期打印输出:
SNP - 实际运行打印结果:
SNW - 问题代码如下:
#include <stdio.h> int main() { int o = '!?zx' ^ '!h4+'; printf("%s\n", &o); return (o ^ o); }
根本原因
这段代码本身大量依赖C标准未定义、实现定义的行为,本身就不具备跨环境输出一致性,输出SNW是当前运行环境下的必然结果:
- 未定义/实现定义行为说明
- 代码中使用的多字符字符常量(即单引号包裹多个字符的写法,如
'!?zx'),其对应的整数值、字符在int内存中的排布顺序属于C标准规定的实现定义范畴,不同编译器、不同硬件平台下的解析结果没有统一标准。 printf的%s格式符要求传入char*类型参数,代码中直接传入int*类型的&o属于未定义行为,C标准不保证该写法的运行结果。
- 代码中使用的多字符字符常量(即单引号包裹多个字符的写法,如
- 当前环境输出SNW的计算逻辑
在主流x86/x86_64小端架构、GCC/Clang等常规编译器环境下,多字符常量按大端规则打包为int值:4字符常量c1c2c3c4对应的int值为(c1 << 24) | (c2 << 16) | (c3 << 8) | c4,结合小端内存低地址存低有效位的规则,计算过程如下:- 计算两个多字符常量的整数值:
'!?zx'对应ASCII值为:'!'=0x21、'?'=0x3F、'z'=0x7A、'x'=0x78,打包后int值为0x213F7A78'!h4+'对应ASCII值为:'!'=0x21、'h'=0x68、'4'=0x34、'+'=0x2B,打包后int值为0x2168342B
- 两个值按位异或得到变量
o的值:0x213F7A78 ^ 0x2168342B = 0x00574E53 - 小端模式下从
&o起始地址开始的4字节内存排布为:- 偏移0字节:0x53 → ASCII字符'S'
- 偏移1字节:0x4E → ASCII字符'N'
- 偏移2字节:0x57 → ASCII字符'W'
- 偏移3字节:0x00 → 字符串终止符'\0'
printf按%s逐字节读取到'\0'停止,自然输出SNW。
- 计算两个多字符常量的整数值:
- 与预期SNP不符的直接原因
代码编写者错误预设了多字符常量的解析规则,且写错了异或使用的字符:要输出SNP需要偏移2字节的字符为'P'(ASCII 0x50),对应第二个多字符常量的第二个字符应为'?' ^ 0x50 = 0x6F(小写字母'o'),而非代码中写的'h'(0x68),异或后得到的字符自然从'P'变成了'W'。
内容的提问来源于stack exchange,提问作者Catty_cat
相关产品推荐
相关产品推荐

