它们具有相同的语义。
常量999
的类型为int
。
int i=999;
char c=i;
i
创建为 type 的对象并使用value进行int
初始化,具有明显的语义。int
999
c
被创建为 类型 的对象char
,并使用 的值进行初始化i
,恰好是999
。该值从 隐式转换int
为char
。
plain 的签名char
是实现定义的。
如果plainchar
是无符号类型,则转换的结果是明确定义的。该值以模减少CHAR_MAX+1
。对于具有 8 位字节 ( CHAR_BIT==8
) 的典型实现,CHAR_MAX+1
将为 256,存储的值为999 % 256
或231
。
如果 plainchar
是有符号类型,并且999
超过CHAR_MAX
,则转换会产生实现定义的结果(或者,从 C99 开始,会引发实现定义的信号,但我知道没有实现会这样做)。通常,对于具有 的 2 的补码系统CHAR_BIT==8
,结果将是-25
。
char c=999;
c
被创建为类型的对象char
。它的初始值是按照我上面描述的完全相同的规则转换为的int
值。999
char
如果CHAR_MAX >= 999
(仅当CHAR_BIT
一个字节中的位数至少为 10 时才会发生),则转换是微不足道的。有用于 DSP(数字信号处理器)的 C 实现CHAR_BIT
,例如设置为 32。这不是您可能在大多数系统上运行的东西。
在第二种情况下,您可能更有可能收到警告,因为它正在转换常量表达式;在第一种情况下,编译器可能不会跟踪i
. 但是一个足够聪明的编译器可以对两者都发出警告,而一个足够幼稚(但仍然完全符合)的编译器则不能对两者都发出警告。
正如我上面所说,当源值不适合目标类型时,将值转换为有符号类型的结果是实现定义的。我想可以想象一个实现可以为常量和非常量表达式定义不同的规则。不过,那将是一个不正当的选择。我不确定即使是 DS9K 也能做到这一点。
至于引用的评论“第一个是赋值,第二个是初始化”,这是不正确的。两者都是初始化;两个代码段中都没有赋值。不同之处在于一个是具有常量值的初始化,另一个不是。顺便说一句,这意味着第二个片段可以出现在文件范围内,在任何函数之外,而第一个片段不能。