是转换int的地址,其值溢出一个signed char到一个指针char UB?



你好,我有这个例子:

int main(){
int x = 300;
char* p = (char*)&x;
printf("%sn", p);
printf("%dn", *p);
}

输出:

,
44
  • 是否存在未定义行为,只要x具有溢出signed char的正值,就将x的地址转换为char*?

  • 为什么我得到这个输出?,44?我试图理解,所以我认为300 % 256 = 44被转换并分配给p,所以它的字符ASCII值是,在我的实现。

你认为和推荐什么?

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

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

printf("%sn", p);将这4个字节解释为C-string。输出

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

理论上,如果300的字节表示不包含空字节,您可以获得UB,因为它会导致printf继续读取x的边界之外的内存,寻找空终止符。但是没有真正的平台可以这样做,所以它应该是安全的。

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


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


x有一个正值,表示signed char溢出

这不是问题。

  • 是未定义的行为castx的地址到char*只要x有一个正的值溢出一个有符号的字符?

不管x的值是多少,这都不是未定义的行为;只要const没有问题,你可以从任何类型的指针到char*指针进行reinterpret_cast操作。

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

  • 为什么我得到这个输出?,44?我试图理解,所以我认为300 % 256 = 44被转换并分配给p,所以它的字符ASCII值是,在我的实现。

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

现在,尝试将其作为字符串打印,您将获得值为0x2C的第一个字符,即','字符,然后是不可打印的字符0x01。下面的0x00字符终止了字符串,所以看到的输出只是,

当以十进制形式打印指针值时,只打印0x2C,即44

相关内容

  • 没有找到相关文章

最新更新