Fil*_*efp 19 c++ language-lawyer c++11 c++14
在标题为由于错误的strcmp参数处理而生成的警告之后,似乎存在一些关于标准实际上保证关于字符类型的值表示的问题.
这看起来很好,但标准是否保证(1)总是会产生真实的?
char unsigned * p1 = ...;
char * p2 = reinterpret_cast<char *> (p1);
*p1 == *p2; // (1)
Run Code Online (Sandbox Code Playgroud)
Fil*_*efp 17
但是在C++ 11标准(N3337)和即将推出的C++ 14(N3797)中都没有这样的保证.
char unsigned * p1 = ...;
char * p2 = reinterpret_cast<char *> (p1);
*p1 == *p2; // (1), not guaranteed to be true
Run Code Online (Sandbox Code Playgroud)
注意:无论char是签名还是未签名,都是特定于实现的; [basic.fundamental]p1.
标准保证每种字符类型;
共享相同数量的存储,对齐要求以及有关位参与的保证意味着将涉及一种类型(unsigned char)的左值转换为另一种(char)是安全的......就实际的转换而言.
3.9.1p1基本类型[basic.fundamental]它是实现定义的,是否
char可以保持负值.可以显式声明字符signed或unsigned.甲
char,一个signed char,和unsigned char占据存储相同量的并具有相同的对准要求(3.11); 也就是说,它们具有相同的对象表示.对于字符类型,对象表示的所有位都参与值表示.对于无符号字符类型,值表示的所有可能位模式表示数字.这些要求不适用于其他类型.
3.9p4类型[basic.types]该对象表示类型的对象的
T是序列Ñunsigned char由类型的对象吸收的对象T,,其中N等于sizeof(T).对象的值表示是保存type值的位集T.
如果我们将unsigned char(UCHAR_MAX)的最大值分配给*p1并且*p2已签名,*p2则无法表示此值.我们将溢出*p2,它最有可能最终具有价值-1.
注意:有符号整数溢出实际上是未定义的行为.
*p1 = UCHAR_MAX;
*p1 == *p2; // (1)
Run Code Online (Sandbox Code Playgroud)
operator==在我们比较之前,双方必须具有相同的类型,目前一方是unsigned char另一方char.
因此,编译器将求助于整体提升以找到可以表示两种类型的所有组合可能值的类型; 在这种情况下,结果类型将是int.
在整体提升之后,语句在语义上等同于int (UCHAR_MAX) == int(-1),当然这是错误的.
小智 14
Run Code Online (Sandbox Code Playgroud)strcmp (buf1, reinterpret_cast<char const *> (buf2));看起来很好,
它是.strcmp获取const char *参数,但在内部将它们转换为const unsigned char *(如果需要),这样即使char签名并且两个不同的字节在查看它们时可以比较相等char,它们在查看时仍会比较不同strcmp.
C99:
7.21字符串处理
<string.h>7.21.1字符串函数约定
3对于本子条款中的所有函数,每个字符都应被解释为具有类型
unsigned char(因此每个可能的对象表示都是有效的并且具有不同的值).
那说,
但是标准是否保证(1)总是产生真实的?
Run Code Online (Sandbox Code Playgroud)char unsigned * p1 = ...; char * p2 = reinterpret_cast<char *> (p1); *p1 == *p2; // (1)
你写的不保证.
char使用二进制补码表示,使用带符号的8位字节进行通用实现.如果*p1是UCHAR_MAX,那么*p2 == -1,并且*p1 == *p2将是假的,因为促销int给他们不同的价值观.
如果您的意思是(char) *p1 == *p2,或者*p1 == (unsigned char) *p2,那么仍然无法保证,那么您确实需要确保如果从数组复制char到数组unsigned char,则不要包含这样的转换.
| 归档时间: |
|
| 查看次数: |
5116 次 |
| 最近记录: |