{int i=999;char c=i;}与{char c=999;}有何不同?

{int i=999;char c=i;}与{char c=999;}有何不同?,c,C,我的朋友说他在网上的某一页上读了这本书,所以它们是不同的,但是这两本书怎么可能是不同的呢 案例1 int i=999; char c=i; 案例2 char c=999; 在第一种情况下,我们将整数i初始化为999,然后用i初始化c,这实际上是999。在第二种情况下,我们直接用999初始化c。除了信息的截断和丢失之外,这两种情况到底有什么不同 编辑 int i=999; char c=i; 这是我刚才提到的链接 一位成员在评论中说--这不是一回事。第一个是分配,第二个是初始化

我的朋友说他在网上的某一页上读了这本书,所以它们是不同的,但是这两本书怎么可能是不同的呢

案例1

 int i=999;
 char c=i;
案例2

 char c=999;
在第一种情况下,我们将整数
i
初始化为
999
,然后用
i
初始化
c
,这实际上是
999
。在第二种情况下,我们直接用
999
初始化
c
。除了信息的截断和丢失之外,这两种情况到底有什么不同

编辑

 int i=999;
 char c=i;
这是我刚才提到的链接

一位成员在评论中说--这不是一回事。第一个是分配,第二个是初始化


因此,这不仅仅是一个编译器优化的问题吗?

这取决于您的编译器和优化设置。看看实际的程序集列表,看看它们有多不同。对于GCC和合理的优化,这两个代码块可能是等效的。

任何优化编译器都只会使int
i=999
局部变量消失,并在这两种情况下将截断的值直接分配给
c
。(假设您没有在任何其他地方使用
i

除了第一个还定义了类型为
int
的对象
i
,语义是相同的

i、 实际上是999


否,
i
是一个变量。从语义上讲,它在c。。。直到运行时才知道该值(即使我们可以清楚地看到它是什么,优化编译器也是如此)。但在案例2中,您将999赋值给一个不合适的字符,因此编译器发出警告。

它们具有相同的语义

常量
999
的类型为
int

int i=999;
char c=i;
i
创建为
int
类型的对象,并用
int
999
初始化,具有明显的语义

c
被创建为类型为
char
的对象,并用值
i
初始化,该值恰好是
999
。该值从
int
隐式转换为
char

plain
char
的签名是实现定义的

如果plain
char
是无符号类型,则转换的结果定义良好。该值按CHAR\U MAX+1的模减少。对于具有8位字节(
CHAR\u bit==8
)的典型实现,
CHAR\u MAX+1
将为256,存储的值将为
999%256
,或
231

如果plain
char
是有符号类型,并且
999
超过
char\u MAX
,转换将产生一个实现定义的结果(或者,从C99开始,引发一个实现定义的信号,但我知道没有实现会这样做)。通常,对于字符位=8的2补系统,结果将是
-25

char c=999;
c
被创建为
char
类型的对象。它的初始值是
int
999
转换为
char
——与我上面描述的规则完全相同

如果
CHAR\u MAX>=999
(只有当
CHAR\u BIT
(一个字节中的位数至少为10)时才会发生这种情况),则转换是微不足道的。例如,
CHAR\u BIT
设置为32的DSP(数字信号处理器)有C实现。在大多数系统上,您可能不会遇到这种情况

在第二种情况下,您可能更容易得到警告,因为它正在转换常量表达式;在第一种情况下,编译器可能无法跟踪
i
的预期值。但是一个足够聪明的编译器可以同时警告这两种情况,而一个足够幼稚(但仍然完全一致)的编译器可以同时警告这两种情况

如上所述,当源值不适合目标类型时,将值转换为有符号类型的结果由实现定义。我认为一个实现可以为常量和非常量表达式定义不同的规则。然而,这将是一个反常的选择;我不确定DS9K是否能做到这一点


至于引用的注释“第一个是赋值,第二个是初始化”,这是不正确的。两者都是初始化;两个代码段中都没有赋值。区别在于一个是具有常量值的初始化,而另一个不是。顺便说一句,这意味着第二个代码段可能出现在任何函数之外的文件范围内,而第一个代码段则不能出现。

请再细化一些。OP不是很聪明。@Rüppell的文化使用
gcc-S
运行它并比较列表。回答不好。问题不在于生成的代码,而在于语言标准定义的语义。在最初的问题中,他真正问的是“这两种情况到底有什么不同?”所以你不应该那么肯定,Jim Balter。“所以你不应该那么肯定”--即使后来的讨论清楚地表明我是对的?从一开始就很清楚,问题不在于它们是否会生成不同的代码。请您再详细说明一下。只需详细说明一下@Jack所说的内容,他的意思是编译器很可能会破坏您的
i
值。这意味着编译后变量将永远不存在,因此
c=999
将是唯一存在的东西,这意味着
情况2
。但是,如果您使用
i
变量,则编译器将保留
i
c
,就像您的案例1一样,并沿着路径继续