初始化变量并在声明后立即为其赋值是否有区别?

Vil*_*ray 2 c assembly initialization c99 variable-assignment

假设一个纯粹的非优化编译器,在初始化变量并在声明后为其赋值时,机器代码是否存在差异?

初始化方法:

int x = 2;
Run Code Online (Sandbox Code Playgroud)

作业方式:

int x;
x = 2;
Run Code Online (Sandbox Code Playgroud)

我使用GCC输出为这两种不同方法生成的程序集,并且两者都产生了一条机器指令:

movl    $2, 12(%esp)
Run Code Online (Sandbox Code Playgroud)

该指令只是将x变量保存的内存设置为值2.GCC可能会对此进行优化,因为它可以识别操作的最终结果; 但我认为这是解释这两个版本的唯一方法.我的理由是两个版本都做同样的事情:将内存的一部分设置为特定值.

那么,如果生成的机器代码相同,那么为什么通常会在术语" 初始化 "和" 赋值 " 之间进行区分?

术语" 初始化 " 是否纯粹用于区分具有特定值的变量,这些变量具有在内存中留下任何垃圾值的那些(非初始化)变量?

aut*_*tic 7

假设一个纯粹的非优化编译器,在初始化变量并在声明后为其赋值时,机器代码是否存在差异?

当然.

  • char fubar[] = "hello world"; 已验证.
  • char fubar[]; fubar = "hello world"; 不是.

更多?

  • int fubar[128] = { [60] = 42 }; 已验证.
  • int fubar[128]; fubar = { [60] = 42 }; 不是.

更多?

  • struct foo bar = { .foo = 13, .bar = 42 }; 已验证.
  • struct foo bar; bar = { .foo = 13, .bar = 42 }; 不是.

更多?

  • const int fubar = 0; 已验证.
  • const int fubar; fubar = 0; 不是.

我可以继续......因此,机器代码可能存在一个,而它很可能不会存在另一个.在那个问题上,您是否听说过C的实现不是编译器?

那么,如果生成的机器代码相同,那么为什么通常会在初始化和赋值之间进行区分?

C编程语言中的变量概念对于低级机器代码表示来说太高级了.在机器代码中,寄存器没有范围.C增加了范围,更不用说类型融合和许多其他与变量相关的方面,以及初始化(你可以从前面的例子中看到,但不幸的是不一样).

术语"初始化"是否纯粹用于区分具有特定值的变量,这些变量具有在内存中留下任何垃圾值的那些(非初始化)变量?

虽然"初始化"的变量不包含任何"垃圾值"(或陷阱表示),但这并不是它唯一的影响.

在我的第一个例子中,初始化将提供否则不完整的数组的大小.使用赋值运算符的等价物将需要显式提供数组的长度和使用strcpy,这结果非常繁琐.

在我的第二个例子中,intat索引60将被初始化为40,而其余的,未初始化的项目将被初始化为0.使用赋值运算符的等价物也将是相当繁琐的.

在我的第三示例中,部件foobar将被初始化为13和42,而剩余,否则未初始化的成员将被初始化为0.使用赋值运算符的等效将是相当繁琐的,虽然我偶尔使用文字来实现类似的化合物结果.

在我的第四个例子中,初始化设置变量将包含的整个生命周期的值.此变量无法分配.


Jen*_*edt 5

添加const限定符时,一个重要的区别就会发挥作用:

int const x = 2;
Run Code Online (Sandbox Code Playgroud)

是有效的C.

int const x;
x = 2;
Run Code Online (Sandbox Code Playgroud)

不是.另一个重要的区别是static变量:

static int x = f();
Run Code Online (Sandbox Code Playgroud)

是无效的C.

static int x;
x = f();
Run Code Online (Sandbox Code Playgroud)

已验证.