是否将其值溢出 singed char 的 int 地址转换为指向 char UB 的指针?

Is casting an address of int whose value overflows a singed char to a pointer to char UB?

你好,我有这个例子:

int main(){

    int x = 300;
    char* p = (char*)&x;
    printf("%s\n", p);
    printf("%d\n", *p);

}

输出:

,
44

您有什么看法和建议?

这里没有UB。一般来说,这样做会违反严格的别名(导致 UB),但有一个例外允许您使用 char 指针访问任何类型。

300 在内存中表示为 4 个字节:44 1 0 0(假设 sizeof(int) == 4,这很常见,并假设小端)。

printf("%s\n", p); 将这 4 个字节解释为 C 字符串。你会通过打印

得到相同的结果
const char str[4] = {44, 1, 0, 0}; // Same as `{',', '', '[=10=]', '[=10=]'}`

理论上,如果 300 的字节表示不包含空字节,您可以获得 UB,因为它会导致 printf 继续读取超出 [=18= 范围的内存],寻找空终止符。但是没有真正的平台出现这种情况,所以应该是安全的。

*p访问x表示中的第一个字节,即44


如果您要在大端平台上尝试此代码,您将分别得到一个空字符串和一个 0,因为 300 的字节表示将是 0 0 1 44.


x has a positive value that overflows a signed char

这不是问题。

  • Is it Undefined Behavior casting the address of x to char* as long as x has a positive value that overflows a signed char?

无论 x 的值如何,这都不是未定义的行为;只要 const.

没有问题,您就可以从任何指针类型到 char* 指针执行 reinterpret_cast

将此值打印为字符串 未定义的行为,但是:您可能在 int 仅使用 16 位的系统上,因此 none可通过 char 指针访问的 int 的字节数可能为 0,导致字节为 0; printf() 因此可以读取保证可访问的内存。

  • Why I got this output? , and 44? I've tried to understand so I thought 300 % 256 = 44 is converted and assigned to p so its character ASCII value is , on my implementation.

您正在使用 32 位 ints 的小端系统。这意味着 300 = 0x12C 被视为数组 { 0x2C, 0x01, 0x00, 0x00 }(小端系统首先存储最低有效字节)。

现在,尝试将其打印为字符串,您会得到第一个值为 0x2C 的字符,即 ',' 字符,后跟一个不可打印的字符 0x01 .以下 0x00 字符终止字符串,因此看到的输出只是 ,.

当将指针值打印为十进制时,唯一打印的是十进制的 0x2C,即 44.