C++ 将未签名的char*强制转换为char*,并将取消引用的指针视为真正指向char*是否安全?

C++ 将未签名的char*强制转换为char*,并将取消引用的指针视为真正指向char*是否安全?,c++,c++11,language-lawyer,c++14,C++,C++11,Language Lawyer,C++14,在题为的问题之后,似乎有一些关于标准在字符类型的值表示方面实际保证了什么的问题 问题 这看起来很好,但标准是否保证(1)始终为真 char无符号*p1=。。。; char*p2=重新解释(p1); *p1==*p2;//(1) 这可能会让你大吃一惊, 但是在C++11标准()中,以及即将推出的C++14()中,都没有这样的保证 operator==的两侧必须具有相同的类型,然后才能进行比较,当前一侧是无符号字符,另一侧是字符 因此,编译器将求助于整数提升,以找到一个可以表示这两种类型的所有组

在题为的问题之后,似乎有一些关于标准在字符类型的值表示方面实际保证了什么的问题


问题 这看起来很好,但标准是否保证(1)始终为真

char无符号*p1=。。。;
char*p2=重新解释(p1);
*p1==*p2;//(1)
这可能会让你大吃一惊, 但是在C++11标准()中,以及即将推出的C++14()中,都没有这样的保证


operator==
的两侧必须具有相同的类型,然后才能进行比较,当前一侧是
无符号字符
,另一侧是
字符

因此,编译器将求助于整数提升,以找到一个可以表示这两种类型的所有组合可能值的类型;在这种情况下,结果类型将是
int

在整数提升之后,该语句在语义上等价于
int(UCHAR_MAX)==int(-1)
,这当然是错误的

你写的东西不能保证

以一个常见的实现为例,使用带符号的
char
,8位字节使用2的补码表示。如果
*p1
UCHAR_MAX
,则
*p2==-1
*p1==*p2
将为假,因为升级到
int
会给它们不同的值


如果您的意思是
(char)*p1==*p2
,或者
*p1==(unsigned char)*p2
,那么这些仍然不能保证,因此您需要确保,如果您从
char
数组复制到
unsigned char
数组,则不包括这样的转换。

Hmmmm。。。我假设char是有符号的。@FilipRoséen refp
char
不能有填充位(将在标准中这样说的地方查看)。我不确定
signed char
是否可以,但如果可以,那么提供
signed char
填充位的实现必须使
char
无符号。不管怎样,
strcmp
实际上并不使用其参数的
char
类型,而是在比较任何参数之前将其转换回
const unsigned char*
。@FilipRoséen refp 3.9.1p1:“对于字符类型,对象表示的所有位都参与值表示。”@hvd注意,在最新的草稿中,仅当使用包含不确定值时,保证不会有未定义的行为。这向我表明,只有未签名的字符才能保证没有陷阱表示。这是一个小错误,在这个问题上没有赋值,也没有溢出。值不相等完全是由于整数提升规则和字符可以有负值的事实。
char const unsigned
确定是命名类型的一种不寻常的方式。为什么要使用
unsigned char
(保存字符而不是小整数)有些人发现字节在[0255]范围内的表示比包括我在内的[128127]范围更直观,而不是
char
?@Walter。此外,显式显示某个内容是字节(无符号字符),而不是字符(字符)也很好。但我认为他想将其解释为字符而不是字节。@walter在显示为字符和字节(%02X)时,它有助于避免符号扩展问题。
char unsigned * p1 = ...;
char          * p2 = reinterpret_cast<char *> (p1);

*p1 == *p2; // (1)
char unsigned * p1 = ...;
char          * p2 = reinterpret_cast<char *> (p1);

*p1 == *p2; // (1), not guaranteed to be true
*p1 = UCHAR_MAX;

*p1 == *p2; // (1)
strcmp (buf1, reinterpret_cast<char const *> (buf2));
char unsigned * p1 = ...;
char          * p2 = reinterpret_cast<char *> (p1);

*p1 == *p2; // (1)