将值溢出signed char的int地址转char*是否为UB及输出结果解析
问题1解答
- 首先,将任意对象的地址强制转换为
char*类型的操作本身不属于未定义行为,这是C标准明确允许的合法操作:标准规定指向对象的指针可转换为字符类型指针,转换后得到的指针指向该对象地址最低的首个字节,通过偏移该字符指针可以遍历访问对象的所有字节表示。 - 你担心的「数值超出signed char表示范围」的问题,仅在你的编译环境中
char默认是signed char类型、且访问到的字节值大于SCHAR_MAX(通常为127)时才会触发,但这种情况属于实现定义行为,不是未定义行为,主流编译器都会按照补码规则直接截断得到对应的有符号值,不会产生不可控的异常。
问题2解答
你的推测完全正确,输出逻辑如下:
- 300的十六进制表示为
0x0000012C,当前主流CPU都是小端序架构,int类型的字节按低位到高位存储,因此地址最低的首个字节值为0x2C,对应十进制数值就是44,ASCII编码中44对应字符,。 - 执行
printf("%d\n", *p)时,直接读取首个字节的整数值输出,因此得到44。 - 执行
printf("%s\n", p)时,因为%s要求传入的是\0结尾的字符串指针,这里你传入的是int对象的字节指针,属于未定义行为,本次输出刚好只有逗号是因为后续字节中很快遇到了值为0的字节,且中间的非0字节是不可打印的控制字符,终端不会显示,所以最终看起来只输出了逗号。
相关建议
- 不要将非字符串对象的指针直接传给
printf的%s占位符,这是明确的未定义行为,可能导致内存越界访问。 - 如果要检查整数的字节表示,建议显式使用
unsigned char*类型转换,避免signed char的符号扩展带来的意料外的结果。 - 涉及跨架构的字节操作时,要提前判断当前平台的大小端序,避免字节顺序不匹配导致的逻辑错误。
内容的提问来源于stack exchange,提问作者Itachi Uchiwa
相关产品推荐
相关产品推荐

