const一词是英文constant的缩写,设立这个关键字的本意,是希望让它所修饰的对象成为一个常量。记得在国家间的外交中,有一个经常用到的术语:“从事与身份不符的活动”,这个const恰恰也正从事着这样的活动,呵呵。C语言可以有三种方法定义一个常量:#define、const和枚举,但只有枚举才是真正的常量,什么是真正的常量?真正的常量是没有存储空间的,是一个右值,这意味着通过任何合法的手段也不会被修改,但被const修饰的对象依然是一个左值,尽管这个对象被const限定,笔者仍然至少可以找到三种合法的手段去修改它,而#define所做的只不过是编译期替换而已,只有枚举常量才能真正做到这一点。const实在不应该被命名为const,这会让人们产生误解,它应该命名为readonly或类似的字眼,意即不能通过被const修饰的对象修改它所指向的对象或者它所代表的对象。但在C的世界里把const称为常量早已是普遍的现象,那我们就只好随大流咯,也称之为常量吧,只要知道它实际上不是真正的常量就行了。
第七章曾经讨论过const int *p;与int * const
p的区别,这两个声明的中文名称常常搞得混乱不堪。第一个声明的const是声明说明符,它修饰p所指向的对象,但p仍然是可变的,这意味着p是一个指向常量的指针,简称常量指针。第二个声明的const是声明符的一部分,它修饰的对象是p,这意味着p是一个常量,而且是一个指针类型的常量,简称指针常量。指针常量又常常被人称为“常指针”或“常指针变量”,常指针变量这个名称有点蹩脚,又常又变的,容易让人摸不着头脑,最好还是不要这样称呼。这里还得再强调一次指针常量与地址常量是不同的,不能把数组名称为指针常量,也不能把指针常量称为地址常量,因为指针常量依然是一个左值,而数组名是一个右值,这里肯定有人会问:“什么?指针常量是一个左值?我没听错吧?”你的确没有听错,C89对于左值是这样定义的:
对象是一个命名的存储区域,左值(lvalue)是引用某个对象的表达式。
换言之,如果一个表达式引用的是一个具有具体存储空间的对象,它就是一个左值!那么既然指针常量是一个左值,为什么却不能给它赋值呢?是因为它受限于赋值表达式的一条规则:赋值表达式的左值不能含有限定词!
为了防止指针指向的常量被修改,C标准对于指针间赋值有一个规定,就是左值必须包含右值的所有限定词。
这就限定了一个指向const对象的指针不能赋值给指向非const对象的指针,但反过来就允许。这个规定初看上去非常合理,但其效用其实只限于一级指针,二级指针间的赋值即使满足规定也不再安全,下面举个例子:
const int i=10;
const int **p1;
int *p2;
p1 = &p2;
*p1 =
&i;
*p2 = 20;
现在你会发现,作为常量的i的值被修改了。i的值被修改的关键原因在*p1=&i;这一句,&i是一个指向常量的一级地址,如果没有二级指针p1,受限于上述规定,作为左值接受这个一级地址的指针就必须也是一个指向常量的一级指针,于是就不能进行下一步赋值20的操作。因此,正由于指向const对象的二级指针p1的出现,使得*p1也是一个指向const的指针,于是*p1=&i能够合法地运行,常量i的值被修改也就成了一个预想中的结果了。有鉴于此,某些编译器也会限定非const二级指针之间的赋值,规定上面的p1=&p2也是非法的。
第七章介绍声明符的指针部分有一种形式:
* 类型限定符表opt 指针
这种形式产生了一种比较复杂的带const的指针,例如:
const int * const *** const ** const p;
这是一个会让人头晕目眩的表达式,声明符部分嵌套了九次,如何辨认谁是const,谁不是const呢?一旦明白了其中的原则,其实是非常简单的。第一和最后一个const大家都已经很熟悉的了。对于藏在一堆*号中的const,有一个非常简单的原则:const与左边最后一个声明说明符之间有多少个*号,那么就是多少级指针是const的。例如从右数起第二个const,它与int之间有4个*号,那么p的四级部分就是const的,下面的赋值表达式是非法的:
**p = (int
*const***)10;
但下面的赋值是允许的:
***p=(int*const**)10;
从左边数起第二个const,它与int之间有1个*,那么p的一级部分是const的,也就是*****p
= (int*const***const*)10;是非法的。
分享到:
相关推荐
本章主要讨论了与指针相关的几个关键知识点,包括指向对象的指针、指向对象成员的指针、this指针、对象数组、以及常量的定义。 1. 指向对象的指针与指向对象成员的指针: - 指向对象的指针是指向一个类实例的指针...
在C++编程语言中,有一些核心概念涉及到对象的指针、`this`指针、const关键字、动态内存管理和函数参数。这些知识点对于理解和编写高效、安全的C++代码至关重要。 1. **对象的指针**:对象的指针是指向某个特定类...
在"第九章 指针与 const"中,`const`关键字在C语言中用于定义常量或者使变量不可变。然而,`const`修饰的对象并非真正的常量,它们仍然有存储空间,并且在某些情况下可以被间接修改。真正的常量是枚举类型,它们没有...
11. 指针与const关键字:可以使用`const`关键字修饰指针,防止指针指向的内容被修改,如`const int* p`表示指针指向的整数不可修改。 12. 指针类型转换:可以将指针从一种类型转换为另一种类型,但需要注意对齐和...
本章主要讲解了C++中数组与指针的相关知识,包括数组的定义、多维数组的概念以及指针的基本使用等。通过上述知识点的学习,可以帮助读者更好地理解和掌握C++中数组与指针的使用技巧。在实际编程过程中,合理利用数组...
在第九章中,我们深入探讨了指针的更多高级应用,包括`main`函数与命令行参数、指向函数的指针变量以及使用堆空间。 首先,`main`函数是每个C程序的入口点。通常,我们看到的`main`函数定义为`int main(void)`,但...
本章主要讨论了数组、指针以及字符串的基本概念和使用方法。 数组是存储相同类型元素的集合,可以通过索引来访问每个元素。例如,数组A[10][5][15]是一个三维数组,它有10个元素,每个元素本身又是一个含有5个元素...
9. 指针与字符串 在C语言中,字符串是以字符数组的形式存在的,而字符数组的名称就是一个指向其首字符的指针。因此,指针在处理字符串时起着关键作用。 以上只是C语言编程,尤其是指针部分的一些基础知识点。实际...
在第九章“指针与数组”中,我们将深入探讨指针的各个方面。 1. **指针的概念与含义** - 指针是一个变量,它存储的是其他变量的内存地址。当我们说“指针”,实际上是指指针变量。 - 地址是系统为变量分配的内存...
9. **const指针和指针const**: `const`关键字可以用来限定指针或指针所指的内容不可变。例如,`const int *p`表示`p`不能改变,但可以修改`*p`;`int * const p`则相反,`p`不能变,但可以修改`*p`。 10. **指针...
第4章指针和const限定符 33.第4章C风格字符串 34.第4章创建动态数组 35.第4章新旧代码的兼容 36.第4章多维数 37.第5章算术操作符 38.第5章关系操作符和逻辑操作符 39.第5章位操作符 40.第5章赋值...
9. **const指针与指针const** `const`关键字可以修饰指针本身(指针不可变)或指针所指向的内容(内容不可变): ```c++ const int *ptrConst; // ptrConst不能改变,但可以通过它修改内容 int *const constPtr;...
### C语言中的数组与指针 在C语言中,数组和指针是非常重要的概念,它们在数据处理和内存管理方面发挥着关键作用。本篇文章将详细介绍C语言中的数组与指针的基本概念、用法以及相互之间的关系。 #### 数组的概念与...
本章主要讨论了指针相关的习题及其答案,涵盖指针的基本操作、指针算术以及指针在数组和字符串中的应用。 1. 指针变量之间的运算:指针变量可以进行减法运算,得到它们之间地址的差值。例如,如果`p1`指向数组的...
根据提供的文件信息,本文将详细解析C语言指针相关的知识点,内容涉及指针的声明、指针与数组、指针与函数、指针运算、指针的指针以及指针与结构体等方面。 1. 指针的声明与赋值 指针需要声明其指向的数据类型,...
#### 九、指针与const 在处理不可修改的数据时,使用 const 指针是非常有用的。 **定义与使用**: - `const int *ptr;` —— 指针指向的数据是不可修改的。 - `int *const ptr = &var;` —— 指针本身不可修改,...
第6章 预处理、const与sizeof 6.1 宏定义 6.2 const 6.3 sizeof 6.4 内联函数和宏定义 第7章 指针与引用 7.1 指针基本问题 7.2 传递动态内存 7.3 函数指针 7.4 指针数组和数组指针 7.5 迷途...
同类型指针可以直接赋值,而不同类型的指针赋值需要进行类型转换,通常使用`static_cast<>`、`const_cast<>`、`dynamic_cast<>`或`reinterpret_cast()`。值得注意的是,`void *`类型的指针可以接受任何类型指针的...
3. **const与指针**:使用const关键字可以创建指向常量的指针或创建不可更改的指针。 ```c const int *p1 = &x; // p1指向的值不可更改 int *const p2 = &x; // p2所指向的地址不可更改 const int *const p3 = ...