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