开始接触 c++ 了— const 和 define 的区别

198 阅读3分钟

这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

在 c/c++ 语言中,提到常量用途,可以是定义数组的长度、阈值或者最大值等。这些常量通常在程序中是不变,在 c++ 中,提供多种定义常量方式,今天我们来聊一聊其中两种常用的方式,分别是 constdefine 方式,他们之间共同之处以及不同之处,以及他们更适合什么样的场合。

由于对 visual studio 的快捷键不太熟悉,所以解释一下注释快捷键 ctrl + K + C

#include <stdio.h>

#define ARRAY_LENGTH 12

//const int ARRAY_LENGTH =12;


int main()
{

	printf("%d\n", ARRAY_LENGTH);
	return 0;
}

通常我们定义常量会用 #define ARRAY_LENGTH 12const int ARRAY_LENGTH =12; 这两种方式来定义一个常量,那么这两种方式又有什么不同呢?只有了解他们之间区别才能更好使用他们,在不同场景和需求选择正确方式来定义一个常量

#define ARRAY_LENGTH 12是在预处理也就是编译之前,将 ARRAY_LENGTH 替换为 12 ,那么对于 const int ARRAY_LENGTH =12; 则是我们定义了变量来储存 12 这是一个变量,所以对于变量赋值发生在编译阶段,同时通过 const 告诉编译器不可以修改这个变量的值,这是一个静态的变量。

那么时候使用 const ,首先这样定义静态变量是可以指定类型,而且我们可以将静态变量生命周期限定到一个作用域范围的。

int main()
{

   const int ARRAY_LENGTH =12;
   printf("%d\n", ARRAY_LENGTH);
   return 0;
}

这样好处是可以避免命名冲突。既然 const 定义静态变量这么好,我们为什么还需要 define 这种方式,define 也有自己有点优点,就是我们通过 gcc 和 clang 这样命令在不通过修改 source 情况下,在编译命令时对这个变量进行赋值

#include <stdio.h>

#define ARRAY_LENGTH 12

int main(){

printf("%d\n",ARRAY_LENGTH)
}
#include <stdio.h>

//#define ARRAY_LENGTH 12

int main(){

printf("%d\n",ARRAY_LENGTH);
}

现在我们就去看看如何在编译过程通过命令语句来更改常量,而无需修改源码就可以更改常量,从而得到通过常量得到不同版本。

all: test

test: test.c

$(CC) $(CFLAGS) -DARRAY_LENGTH=12 $< -o $@

$(CC) $(CFLAGS) -DARRAY_LENGTH=120 $< -o $@.big

clean:

$(RM) test

$(RM) -r *.dSYM

我们现在将 Makefile 文件进行适当的修改,将其恢复原有的模样。

all: test

test: test.c

$(CC) $(CFLAGS) $< -o $@

clean:

$(RM) test

$(RM) -r *.dSYM

通过 const 定义常量是,首先我们明确地告诉这个变量是常量,而且明确其类型。而且这样常量是对应于一个作用域,往往不是全局的,这样也就是避免了命名冲突。

int main(){

const int ARRAY_LENGTH = 12;

printf("%d\n",ARRAY_LENGTH);

}
ARRAY_LENGTH = 120;

当然我们可以一些方法来实现对常量的修改,例如如下方式,不过既然我们将其定义为常量,就不要随意将其修改,不然也就是失去其常量含义。

int main(){

const int ARRAY_LENGTH = 12;

int *p = &ARRAY_LENGTH;

*p = 120;

printf("%d\n",ARRAY_LENGTH);

}
test.c:11:14: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
     int *p = &ARRAY_LENGTH;