C/C++ 语言关于 const

const 关键字用来保护数据不被修改,简而言之就像常量一样,它类似于 ”符号常量” #define指令。

#define“符号常量”宏定义是这样:

1
#define PI 3.14159

宏定义的本质其实就是字符替换,很容易出错,所以要特别注意加括号()

const变量这样声明:

1
const double PI = 3.14159;

const的用法相比#define形式的”符号常量”更加灵活。可以创建const数组、const 指针、指向 const 的指针

举例说明:

1.

1
2
const int days[] = {1, ...};  
days[0] = 5; // 编译出错,不允许修改值。

2.

1
2
3
4
5
6
double rates[] = {1.0, ...};  
const double *pd = rates;
...
*pd = 5.5; // 不允许
pd[0] = 5.5; // 不允许
rates[0] = 3.3; // 允许 因为 rates 没有被 const 限制

3.

const数据非const数据的地址初始化为指向const指针或为其赋值是合法的:

1
2
3
4
5
double rates[] = {88.99, ...};  
const double locked[] = {0.08, ...};
const double *pc = rates; // 有效
pc = locked; //有效
pc = &rates[1]; // 有效

然而,只能把非const数据的地址赋给普通指针:

1
2
3
4
5
6
double rates[] = {88.99, ...};  
const double locked[] = {0.08, ...};
double *pnc = rates; // 有效
pnc = locked; // 无效
pnc = &rates[3]; // 有效
pnc = locked; // 无效可以这样理解,如果其有效那岂不是可以通过指针pnc修改locked[]数组的值了,这是不允许的。

申明一个函数:

1
void show_arry(const double *ar, int n);

由以上可知,函数show_arry(const double *ar, int n)既可以接受普通数组作为参数,又可以接受const数组作为参数。因为,这两种参数都可以初始化const修饰的指针。

4.

const 修饰的其他两种位置:

1
2
3
4
double rates[] = {1, ...};  
double const *pc = rates; // pc 指向数组的开始位置
pc = &rates[3]; // 不允许,不能修改 pc 的指向
*pc = 1.23; // 可以的,允许修改 pc 所指向地址的值

使用两次const修饰指针;

1
2
3
4
5
double rates[] = {1, ...};  
const double const *pc = rates; // pc 指向数组的开始位置
pc = &rates[3]; // 不允许,不能修改 pc 的指向
*pc = 1.23; // 不允许,不允许修改 pc 所指向地址的值
const的使用在 C++ 中应该是一样的。

5.

以上为 C 语言所有,而 C++ 有些不一样。

C++ 允许在声明数组大小时使用 const 整数,而 C 是不允许的。C++ 的指针赋值检查也更为严格:

1
2
3
4
const int y;  
const int *p2 = &y;
int *p1;
p1 = p2; // C++中不允许这样做,但 C中只给出警告;

C++ 中不允许把 const 指针赋给非 const 指针。而 C 是可以的。上面的代码示例中,如果通过p1修改 y的值,其行为是未定义的。

这里还必须注意的的地方是,把 const 指针赋给非 const 指针是不安全的,因为这样可以通过使用新的指针改变 const 指针指向的数据。编译器可能给出警告,然而执行这样的代码是未定义的。不过,把非 const 指针赋给 const 指针没有问题。



参考:

1. 《C Primer Plus》
感谢支持!