C/C++宏,枚举,常量

在C/C++中,宏,枚举,常量都可以表示“常量”,即不变的值。究竟三者有什么区别,本质是什么。下面来证实一下:

1先上个最简单程序,宏的

test_macro.c

#include<stdio.h>

#define ONE 1
#define TWO 2
#define THREE 3

int main(void)
{
   printf("%d\n",ONE);
   printf("%d\n",TWO);
   printf("%d\n",THREE);
   return 0;
}

将其预编译

gcc -E test_macro.c -o test_macro.i

得到下面结果:

//以上省略
# 2 "test_macro.c" 2





int main(void)
{
   printf("%d\n",1);
   printf("%d\n",2);
   printf("%d\n",3);
   return 0;
}

可见在预编译阶段宏已被替换

再将test_macro.i 进行编译

gcc -S test_macro.i -o test_macro.s

得:

	.file	"test_macro.c"
	.section	.rodata
.LC0:
	.string	"%d\n"
	.text
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	andl	$-16, %esp
	subl	$16, %esp
	movl	$.LC0, %eax
	movl	$1, 4(%esp) #ONE
	movl	%eax, (%esp)
	call	printf
	movl	$.LC0, %eax
	movl	$2, 4(%esp)  #TWO
	movl	%eax, (%esp)
	call	printf
	movl	$.LC0, %eax
	movl	$3, 4(%esp)  #THREE
	movl	%eax, (%esp)
	call	printf
	movl	$0, %eax
	leave
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
	.section	.note.GNU-stack,"",@progbits

所有的宏都成了立即数


2第二个程序测试枚举

test_enum.c

#include<stdio.h>

enum
{
   ONE = 1,
   TWO = 2,
   THREE = 3
};

int main(void)
{
   printf("%d\n",ONE);
   printf("%d\n",TWO);
   printf("%d\n",THREE);
   return 0;
}

将其预编译:

gcc -E test_enum.c -o test_enum.i

得:

# 2 "test_enum.c" 2

enum
{
   ONE = 1,
   TWO = 2,
   THREE = 3
};

int main(void)
{
   printf("%d\n",ONE);
   printf("%d\n",TWO);
   printf("%d\n",THREE);
   return 0;
}

不管预编译时期的事

将其编译

gcc -S test_enum.i -o test_enum.s

得:

	.file	"test_enum.c"
	.section	.rodata
.LC0:
	.string	"%d\n"
	.text
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	andl	$-16, %esp
	subl	$16, %esp
	movl	$.LC0, %eax
	movl	$1, 4(%esp)  #ONE
	movl	%eax, (%esp)
	call	printf
	movl	$.LC0, %eax
	movl	$2, 4(%esp) #TWO
	movl	%eax, (%esp)
	call	printf
	movl	$.LC0, %eax
	movl	$3, 4(%esp)#THREE
	movl	%eax, (%esp)
	call	printf
	movl	$0, %eax
	leave
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
	.section	.note.GNU-stack,"",@progbits

可见在编译时期,枚举被替换成立即数


再看个枚举的例子:

test_enum2.c

#include<stdio.h>

enum Player
{
   CURRY,
   DURANT,
   JAMES,
   WESTBROOK,
};

int main(void)
{
   Player p1 = CURRY;
   Player p2 = DURANT;
   Player p3 = JAMES;
   p3 = WESTBROOK;
   return 0;
}

将其编译(在gcc编译不过的,c++的语法)

g++ -S test_enum2.c

得:

	.file	"test_enum2.c"
	.text
.globl main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$16, %esp
	movl	$0, -4(%ebp)
	movl	$1, -8(%ebp)
	movl	$2, -12(%ebp)
	movl	$3, -12(%ebp)
	movl	$0, %eax
	leave
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
	.section	.note.GNU-stack,"",@progbits

可见枚举CURRY,DURANT,JAMES在编译期被替换成了1,2,3,占一个int类型的大小


3.下面看常量的代码:

test_const1.c

#include<stdio.h>

void main()
{
    int value1 = 10;
    const int nConst1 = 5;
    int* pConst1 = (int*)&nConst1;
    *pConst1 = 6;
    printf("%d\n",nConst1);
}

预编译:gcc -E test_const1.c -o test_const1.i

# 2 "test_const1.c" 2

void main()
{
    int value1 = 10;
    const int nConst1 = 5;
    int* pConst1 = (int*)&nConst1;
    *pConst1 = 6;
    printf("%d\n",nConst1);
}

不管预编译的事

将其编译 : gcc -S test_const1.i -o test_const1.s 得:

	.file	"test_const1.c"
	.section	.rodata
.LC0:
	.string	"%d\n"
	.text
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	andl	$-16, %esp
	subl	$32, %esp
	movl	$10, 28(%esp) #变量value1
	movl	$5, 24(%esp)  #常量nConst1
	leal	24(%esp), %eax
	movl	%eax, 20(%esp)
	movl	20(%esp), %eax
	movl	$6, (%eax)  #通过指针pConst来改变常量nConst1的值
	movl	24(%esp), %edx
	movl	$.LC0, %eax
	movl	%edx, 4(%esp)
	movl	%eax, (%esp)
	call	printf
	leave
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
	.section	.note.GNU-stack,"",@progbits

由此可知声明个常量其实跟变量在编译后没有本质的区别,只是在编译器期间,编译器会检查是否有对const类型有修改,若有修改则编译器报错,cosnt完全由编译器控制其不被修改。我们甚至可以使用指针将常量类型去除,从而达到修改常量的值。

而宏是在预编时被替换成表达式,而枚举也在编译时期被展开成了相应的立即数。

可以这样说,宏在预编译时期确定,枚举在编译时期确定。而const常量可以算是在运行时确定。

有时候我们改了一个宏的值,就可能造成怎个项目被重新编译一遍。如果不想浪费这么多的编译时间,有时我们就会推荐使用枚举和常量。

const常量不能算是真正的常量,算个限制型的变量吧。

说的不一定完全正确啊,请多多指正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值