int j; // Переменная типа int, в нее можно писать, что угодно.
int * pi; // Указатель на переменную int, в которую можно писать: *pi = 5;
const int * cpi; // Указатель на константную переменную int,
// которую можно только читать: о = *cpi;
// Сам указатель можно менять: cpi = &j;
const int * const ccpi; // Константный указатель на константную переменную.
// И переменную, на которую он указывает, можно только читать,
// и сам указатель нельзя изменять...
这些记录最容易从右到左阅读。例如,
本公告
声明了一个名为 的指针
blah_blah
,它指向一个 const 指针(因为从右到左看时 const 限定符在 * 之前),它指向一个 const 类型的对象char
。下面是一个简单程序的例子,它使这个声明更容易理解。
它会输出到控制台
为清楚起见,您可以输入
typedef
名称在这种情况下,变量
blah_blah
是指向 const 类型的 const 对象的指针char
。我认为如果您遵循指针定义的语法,将更容易理解这些声明。
C标准中的指针定义如下
也就是说,* 后面可以跟一个引用它的资格列表。
因此,前面的声明可以写成
您还可以使指针本身
blah_blah
保持不变。但如果它具有自动内存持续时间,则必须在声明时显式初始化它。例如或者
这是一个演示程序,其中指针本身
blah_blah
也被声明为 const。该指针的声明被读取为指向 char 类型常量对象的常量指针的常量指针。
具有原型的函数声明可以省略参数标识符。
下面是这样一个程序。
由于同一个函数可以有多个声明(没有它的定义),所以上面所有的函数都声明了同一个函数。直接引用参数的所谓顶级限定符可以从函数声明中删除。也就是说(另一个例子)这些函数对声明相同的函数
和
C 和 C++ 通常使用对象访问路径的 [非正式/半正式] 概念。即:指向对象的指针(或引用)是访问该对象的路径。访问路径是const或non-const。不能通过常量访问路径修改对象,但可以通过非常量访问路径进行修改(前提是对象本身是可修改的)。对于同一个对象,我可以引导常量和非常量访问路径。
您给出的
const
在指针声明的更深层嵌套(即左侧*
)中使用修饰符的示例仅控制访问路径的恒定性,即它们允许或禁止通过此访问路径修改指向的对象。(只有你的最后一个例子来自该系列,其中最右边的例子
const
指定integer
了指针本身的常量,而不是指向对象的访问路径。)如果通过 const 和非 const 访问路径都可以看到同一对象,那么通过非 const 访问路径对该对象所做的修改将立即通过 const 访问路径可见。
也就是说,您的修饰符
const
并没有说不能更改指定的对象。它们只是阻止您通过该特定访问路径修改指向的对象。因此,管理访问路径的稳定性基本上是一种自律的手段。然而,在从一开始就正确并积极地使用对象的恒常性的代码中,不使用这个工具是不可能的。C 和 C++ const 正确性规则允许您自由地将非常量访问路径转换为 const 路径。
但反向转换是不可能的。(通过使用
const_cast
或 C 风格的转换,可以将 const 访问路径“强行”转换为非常量访问路径,但那是另一回事了。)可以额外注意到,C 和 C++ 语言的常量正确性规则有些不同,这导致了一些在 C 语言中一直存在至今,在 C++ 语言中早已消除的“不合逻辑”
这有时会干扰 C 中常量访问路径的完整使用。
好吧,看,例如:
这或多或少清楚吗?
更复杂的选项可能包括,例如,指向
ccpi
上述常量指针的常量指针:)