现在我们已经掌握了更多类型,事实证明我们可以给这些类型添加一些额外的属性来控制它们的行为。这些属性就是类型限定符(type qualifiers)和存储类说明符(storage-class specifiers)。

16.1 Type Qualifiers

这些将允许你声明常量值,同时也向编译器提供它可以利用的优化提示。

16.1.1 const

这是你最常见到的类型限定符。它表示变量是常量,任何试图修改它的操作都会导致编译器报错。

const int x = 2;

x = 4;  // 编译器会发出错误提示,不能给常量赋值

你不能改变一个 const 值。

你经常会在函数的参数列表中看到 const

void foo(const int x)
{
    printf("%d\\n", x + 30);  // 没问题,这里没有修改 "x"
}

这一点有点复杂,因为在指针方面存在两种用法,它们有不同的含义。

首先,我们可以让指针指向的内容不可变。你可以通过在类型名之前(指针符号 * 之前)放置 const 来实现这一点。

int x[] = {10, 20};
const int *p = x;

p++;          // 可以修改指针 p,本身没有问题

*p = 30;      // 编译器报错!不能修改指针所指向的内容

有些令人困惑的是,下面这两种写法是等价的:

const int *p;  // 不能修改 p 指向的内容
int const *p;  // 也不能修改 p 指向的内容,跟上一行是一样的

总结来说,我们不能修改指针指向的内容,但可以修改指针本身。那么如果想反过来呢?也就是说,我们想允许修改指针指向的内容,但不允许修改指针本身,该怎么办?

只需在声明中将 const 放在星号 * 后面:

int *const p;  // 不能通过指针运算修改 "p"
p++;          // 编译器报错!

但我们可以修改它们所指向的内容:

int x = 10;
int *const p = &x;

*p = 20;      // 将 "x" 赋值为 20,没问题

你也可以让两者同时是 const