关于 C 中类型转换的简单问题,假设这行代码:
signed char a = 133;
Run Code Online (Sandbox Code Playgroud)
由于有符号字符的最大值是128,上面的代码是否具有implementation defined根据第三条转换规则的行为?
如果值不能用新类型表示并且它不是无符号的,那么新类型是有符号的并且值不能在其中表示;要么结果是实现定义的,要么引发实现定义的信号。
首先,133 不是无符号的。因为它总是适合于int,所以它的类型是int, 并且是有符号的(此外在 C99+ 中,所有无后缀的十进制常量都是有符号的!要获得无符号数,必须在末尾添加U/ u)。
其次,这不是演员表,而是转换。C 中的强制转换是显式转换(或非转换)到特定类型,标记为构造(type)expression。在这种情况下,您可以编写初始化以使用显式强制转换
signed char a = (signed char)133;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它不会改变初始化的行为。
第三,这确实是一个初始化,而不是一个赋值,所以对于什么是可接受的表达式,它有不同的规则。如果这个初始化器用于一个具有静态存储期的对象,那么初始化器必须是某种编译时常量。但是对于这种特殊情况,赋值和初始化都会以相同的方式进行转换。
现在我们开始讨论第三个整数转换规则是否适用- 为此,您需要知道前两个规则是什么:
目标类型是整数类型(不是_Bool),其中的值可以表示(在这种情况下不适用,因为众所周知,如果 133SCHAR_MAX是 127,则无法表示)
目标类型是无符号的(其实不是)
所以我们得到了C11 6.3.1.3p3:
- 否则,新类型是有符号的,值不能在其中表示;要么结果是实现定义的,要么引发实现定义的信号。
问题是它是否具有实现定义的行为——是的,实现必须记录会发生什么——它如何计算结果,或者它会在那种情况下发出哪个信号。
当值无法在该类型的对象中表示时,将整数转换为有符号整数类型的结果或产生的信号(C90 6.2.1.2、C99 和 C11 6.3.1.3)。
转换为宽度为 N 的类型,该值以 2^N 为模减少到类型的范围内;没有发出信号。
Clang“文档”是一个不太容易访问的“小”,你只需要阅读源代码......