编程语言漫谈之「初始化与赋值」——以C++和汇编语言为示例
1. 赋值时汇编做了什么
当我们在C++中写下如下代码:
int main() {
int a = 10;
return 0;
}
这是一个简单的整数类型变量a的初始化赋值. 我们知道, 如果只定义了一个变量,而没有进行初始化, 后面取这个值时,可能会取出一串奇怪的数字.
那么回到最基本的汇编语言, 赋值操作做了什么?
main:
push rbp ; 保存旧的基址指针
mov rbp, rsp ; 设置新的基址指针
sub rsp, 16 ; 为局部变量分配栈空间
mov DWORD PTR [rbp-4], 10 ; 将 10 存储到局部变量 a 的栈位置
mov eax, 0 ; 将返回值设置为 0
leave ; 恢复旧的基址指针
ret ; 返回调用者
2. 在变量定义时做初始化, 与在使用时才进行初始化, 有区别吗?
在static 修饰局部变量时, 是有区别的
例如,
#include <iostream>
void func() {
static int a = 10; // 定义时直接初始化
std::cout << "a: " << a << std::endl;
a++;
}
int main() {
func(); // 第一次调用,a 被初始化为 10,然后自增为 11
func(); // 第二次调用,a 保持其上次的值 11,然后自增为 12
func(); // 第三次调用,a 保持其上次的值 12,然后自增为 13
return 0;
}
而如果在使用时才进行初始化:
#include <iostream>
void func() {
static int a; // 只声明但未显式初始化
a = 10; // 每次调用函数时都将 a 赋值为 10
a++; // 自增
std::cout << "a: " << a << std::endl;
}
int main() {
func(); // 第一次调用, 11
func(); // 第二次调用, 11
func(); // 第三次调用, 11
return 0;
}