C:如果x是char类型,那么在x=~x中(详细)会发生什么?

C:如果x是char类型,那么在x=~x中(详细)会发生什么?,c,type-conversion,operators,C,Type Conversion,Operators,如果我们有以下代码: char x = -1; x =~x; 在带有MS VS编译器(部分支持C99)的x86平台上,当它运行时会发生什么详细情况 据我所知,发生以下情况(如果我错了,请纠正我): x被分配值-1,该值由位模式0xff表示,因为字符由一个字节表示 ~运算符将x提升为int,也就是说,它在内部使用位模式0xFFFFFF ~运算符的结果是0x00000000(int类型) 要执行分配,应(主要)应用整数提升。因为在我们的例子中,右边的操作数是int,所以不会发生转换。左侧的操作数

如果我们有以下代码:

char x = -1;
x =~x;
在带有MS VS编译器(部分支持C99)的x86平台上,当它运行时会发生什么详细情况

据我所知,发生以下情况(如果我错了,请纠正我):

  • x被分配值-1,该值由位模式0xff表示,因为字符由一个字节表示
  • ~运算符将x提升为int,也就是说,它在内部使用位模式0xFFFFFF
  • ~运算符的结果是0x00000000(int类型)
  • 要执行分配,应(主要)应用整数提升。因为在我们的例子中,右边的操作数是int,所以不会发生转换。左侧的操作数转换为int。赋值结果为0x00000000
  • 作为副作用,分配的左侧被分配值0x00000000。由于x是char类型,因此存在另一个隐式转换,它将0x00000000转换为0x00

事实上发生的事情太多了,我觉得有些困惑。特别是:我对最后一次隐式转换(int到char)的理解正确吗?如果分配的结果不能存储在字符中,会发生什么情况?

确实
~x
int
类型

如果
char
unsigned
,则返回到
char
的转换是明确定义的。当然,如果值在
char
支持的范围内,那么它也是定义良好的

如果
char
有符号的
,则
~x
char
的转换是实现定义的,并且可能会引发实现定义的信号

在您的例子中,您有一个带有2的补码
int
和2的补码
char
,因此
~x
被观察为0的平台


请注意,MSVC并不完全支持任何C标准,它也不声称支持。

您几乎是正确的,但遗漏了
char
具有实现定义的签名。它可以是有符号的,也可以是无符号的,这取决于编译器

在这两种情况下,8位2的补码字符的位模式实际上是0xFF,而不管其符号性如何。但是如果
char
是有符号的,整数提升将保留符号,并且在32位计算机上仍然有值
-1
,二进制0xFFFFFF。但是如果
char
是无符号的,
-1
将在赋值时转换为
255
,整数提升将给出
255
0x000000FF
)。所以你会得到不同的结果

关于
~
的整数提升,它的右侧只有一个运算符,并且该运算符已提升

最后,将结果分配回
char
,结果将再次取决于签名。在从
int
赋值到
char
时,将有一个隐式的“左值转换”。结果是实现定义的-很可能得到
int
的最低有效字节


从中我们可以学到:

  • 切勿将
    char
    用于存储整数值或算术运算。仅用于存储字符。相反,请使用
    uint8\u t
  • 切勿对可能有符号的操作数或通过隐式提升进行静默签名的操作数执行位算术
  • 除非操作数是
    无符号int
    或更大的无符号类型,否则~运算符尤其危险
据我所知,发生以下情况(如果我错了,请纠正我):

x被分配值-1,该值由位模式0xff表示,因为字符由一个字节表示

1
是类型为
int
的整数常量
-
将该值取反为-1,并保持为
int
-1被分配给
字符x
。如果该
char
已签名,则
x
的值为-1。如果
char
是无符号的,
x
接受
char\u MAX
的值,该值也是
UCHAR\u MAX
。“位模式0xff”在这里还不相关

~运算符将x提升为int,也就是说,它在内部使用位模式0xFFFFFF

x
被提升为
int
(或
unsigned
,在
CHAR\u MAX
=
UINT\u MAX
的罕见机器上,我们将忽略这一点)。
int
至少为16位。当-1的值被编码为绝大多数公共2的补码时,它是一个全1位模式。(其他可能的编码-我们也将忽略这一点)。如果
x
的值为
UCHAR\u MAX
,则
x
将具有位模式
00…00 1111 1111
——假设为8位
char
。其他宽度可能-另一件我们将忽略的事情

~运算符的结果是0x00000000(int类型)

是,(除非
CHAR\u MAX==UINT\u MAX
,在这种情况下,它是
unsigned
且值为11…11 0000 0000)

要执行分配,应(主要)应用整数提升。因为在我们的例子中,右边的操作数是int,所以不会发生转换。左侧的操作数转换为int。赋值结果为0x00000000

由于分配原因,此处没有整数促销。由于
~
,促销已发生。将发生类型更改,将
int
分配给
char
。那不是晋升。结果的类型为
char
。作为缩小范围的一部分,0的值不会出现范围问题,并导致值为0,然后键入
char
。11…11 0000 0000的值将通过实现定义的行为,可能会导致值0,并且肯定会键入
char

代码是b