是否将其值溢出 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
只要x
有一个溢出signed char
的正值,就把x
的地址转换成char*
是不是未定义行为?
为什么我得到这个输出? ,
和 44
?我试图理解所以我认为 300 % 256 = 44
被转换并分配给 p
所以它的字符 ASCII 值在我的实现中是 ,
。
您有什么看法和建议?
这里没有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 位 int
s 的小端系统。这意味着 300 = 0x12C
被视为数组 { 0x2C, 0x01, 0x00, 0x00 }
(小端系统首先存储最低有效字节)。
现在,尝试将其打印为字符串,您会得到第一个值为 0x2C
的字符,即 ','
字符,后跟一个不可打印的字符 0x01
.以下 0x00
字符终止字符串,因此看到的输出只是 ,
.
当将指针值打印为十进制时,唯一打印的是十进制的 0x2C
,即 44
.
你好,我有这个例子:
int main(){
int x = 300;
char* p = (char*)&x;
printf("%s\n", p);
printf("%d\n", *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("%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 asigned char
这不是问题。
- Is it Undefined Behavior casting the address of
x
tochar*
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?
,
and44
? I've tried to understand so I thought300 % 256 = 44
is converted and assigned top
so its character ASCII value is,
on my implementation.
您正在使用 32 位 int
s 的小端系统。这意味着 300 = 0x12C
被视为数组 { 0x2C, 0x01, 0x00, 0x00 }
(小端系统首先存储最低有效字节)。
现在,尝试将其打印为字符串,您会得到第一个值为 0x2C
的字符,即 ','
字符,后跟一个不可打印的字符 0x01
.以下 0x00
字符终止字符串,因此看到的输出只是 ,
.
当将指针值打印为十进制时,唯一打印的是十进制的 0x2C
,即 44
.