怎么样{int i = 999; char c = i;}与{char c = 999;}不同?
我的朋友说他在某些页面上看到它们是不同的,但两者怎么可能不同呢?
情况1
int i=999; char c=i;
案例2
char c=999;
在第一种情况下,我们将整数i
初始化为999
,然后用i
初始化c
,实际上是999
在第二种情况下,我们用999
直接初始化c
。除了信息的截断和丢失,这些是怎么回事两种情况不同?
编辑
这是我正在谈论的链接
为什么在将int转换为char时没有溢出警告
一位评论的成员说 – 这不是一回事。 第一个是赋值,第二个是初始化
那么这不仅仅是编译器的优化问题吗?
它们具有相同的语义。
常量999
的类型为int
。
int i=999; char c=i;
i
创建了int
类型的对象,并使用int
值999
初始化,具有明显的语义。
c
被创建为char
类型的对象,并使用i
的值初始化,恰好是999
。 该值隐式地从int
转换为char
。
plain char
的签名是实现定义的。
如果plain char
是无符号类型,则转换结果已明确定义。 该值以模数CHAR_MAX+1
减少。 对于具有8位字节( CHAR_BIT==8
)的典型实现, CHAR_MAX+1
将为256,并且存储的值将为999 % 256
或231
。
如果plain char
是有符号类型,并且999
超过CHAR_MAX
,则转换产生实现定义的结果(或者,从C99开始,引发实现定义的信号,但我知道没有实现这样做的实现)。 通常 ,对于CHAR_BIT==8
的二进制补码系统,结果为-25
。
char c=999;
c
被创建为char
类型的对象。 它的初始值是转换为char
的int
值999
– 与我上面描述的完全相同的规则。
如果CHAR_MAX >= 999
(仅当CHAR_BIT
,一个字节中的位数至少为10时才会发生),那么转换是微不足道的。 有一些用于DSP(数字信号处理器)的C实现,其中CHAR_BIT
设置为,例如,32。在大多数系统上,这不是你可能遇到的问题。
你可能更有可能在第二种情况下得到警告,因为它正在转换一个常量表达式; 在第一种情况下,编译器可能无法跟踪i
的预期值。 但是一个足够聪明的编译器可以警告两者,并且一个足够幼稚(但仍然完全符合)的编译器可以警告两者。
如上所述,当源值不适合目标类型时,将值转换为有符号类型的结果是实现定义的。 我想可以想象一个实现可以为常量和非常量表达式定义不同的规则。 不过,那将是一个不正当的选择; 我不确定DS9K是否能做到这一点。
至于引用的注释“第一个是赋值,第二个是初始化”,这是不正确的。 两者都是初始化; 两个代码段中都没有赋值。 不同之处在于,一个是具有常量值的初始化,而另一个不是。 顺便说一句,这意味着第二个片段可能出现在任何函数之外的文件范围内,而第一个片段则不能。
任何优化编译器都会使int i = 999
局部变量消失,并在两种情况下将截断值直接赋值给c
。 (假设你没有在其他任何地方使用i
)
这取决于您的编译器和优化设置。 看看实际的assembly清单,看看它们有多么不同。 对于GCC和合理的优化,这两个代码块可能是等价的。
除了第一个还定义类型为int
的对象i
,语义是相同的。
我,实际上是999
不, i
是一个变量。 从语义上讲,它在c初始化时没有值……直到运行时才会知道该值(即使我们可以清楚地看到它将是什么,并且优化编译器也是如此)。 但是在第2种情况下,你将999分配给一个不适合的字符,因此编译器会发出警告。