宏常量
- 定义:
#define
定义常量名称,编译器对其进行编译时,会将代码中的宏名替换成对应信息 - 作用: 宏常量可以增加代码的可读性、易于修改和维护.但是要注意,宏常量是纯文本替换,不做任何类型检查,也不会考虑作用域的概念。因此,使用宏常量可能会导致代码中的错误,而且它们不具有变量的属性,只是简单的文本替换。
//定义一个宏常量
#define HP 100;
//定义了一个名为 Add 的宏,它接受两个参数 a 和 b,并返回它们的和
#define Add(a,b) ((a) + (b))
int a = Add(1,2);
//在编译器进行编译时,会直接将 Add(1,2) 替换成 3,
//在反汇编中的体现
mov dword ptr ds:[ebp - 0x4],0x3
//这种宏定义虽然方便,但在使用时要小心确保参数类型和宏展开后的运算逻辑是符合预期的。
const常量
- 安全性和可维护性: 通过将某些值标记为常量,可以防止其在程序中被意外修改,从而提高代码的安全性和可维护性。
- 可读性: 使用常量名称可以增加代码的可读性和可理解性,因为常量名称通常比硬编码的值更具有描述性。
- 编译器优化: 编译器可以利用常量的不可变性进行优化,提高代码的执行效率。
要注意,const
常量必须在声明时进行初始化,且其值在后续程序执行期间不可改变。
局部const常量
- 局部的
const
常量是在函数或代码块内部声明的常量,它的作用域仅限于声明它的那个函数或代码块内部。这种常量的特点是其值在声明后不能被修改,但只在其声明的范围内有效。 - 在反汇编中,局部const常量和局部变量是没有区别的,不可写是由编译器限制的
const int a = 100;
//受编译器限制,不可以直接写 a = 200;
//有两种方法,可以修改这个const常量
//1. 数组越界的方式
const int a = 1;
int Arr[] = { 1,2,3 };
Arr[2] = 1;
printf("%d \n", a);
Arr[5] = 10;
printf("%d \n", a);
//因为局部const常量也是保存在栈区的,所以可以通过数组越界的方式,去修改
//2. 指针修改
const int a = 1;
int* p = &a;
p = 10;
全局const常量
-
全局
const
常量是在程序运行之前就被静态地存储在内存中的。这些常量在程序启动时被初始化,然后一直存在于程序的整个生命周期内,它们的值是固定的且无法被修改。 -
因为全局const常量存储在程序的只读内存区域,所以想修改全局const常量就需要先修改该物理页的属性,修改成可读可写