const几种用法

 一、const变量

        1、限定符声明变量只能被读
   const int i=5;
   int j=0;
   ……
   i=j;  //非法,导致编译错误
   j=i;  //合法
   2、 必须初始化
   const int i=5;    //合法
   const int j;      //非法,导致编译错误
   3、在另一连接文件中引用const常量
   extern const int i;    //合法
   extern const int j=10;  //非法,常量不可以被再次赋值
   4、便于进行类型检查
   用const方法可以使编译器对处理内容有更多了解。
   #define I=10
   const long &i=10;  /*dapingguo提醒:由于编译器的优化,使得在const long i=10; 时i不被分配内存,而是已10直接代入以后的引用中,以致在以后的代码中没有错误,为达到说教效果,特别地用&i明确地给出了i的内存分配。不过一旦你关闭所有优化措施,即使const long i=10;也会引起后面的编译错误。*/
   char h=I;      //没有错
   char h=i;      //编译警告,可能由于数的截短带来错误赋值。
   5、可以避免不必要的内存分配
   #define STRING "abcdefghijklmnn"
   const char string[]="abcdefghijklmn";
   ……
   printf(STRING);  //为STRING分配了第一次内存
   printf(string);  //为string一次分配了内存,以后不再分配
   ……
   printf(STRING);  //为STRING分配了第二次内存
   printf(string);
   ……
   由于const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

       6、可以通过函数对常量进行初始化

   int value();
   const int i=value();
   dapingguo说:假定对ROM编写程序时,由于目标代码的不可改写,本语句将会无效,不过可以变通一下:
   const int &i=value();
   只要令i的地址处于ROM之外,即可实现:i通过函数初始化,而其值有不会被修改。
   7、是不是const的常量值一定不可以被修改呢?
   观察以下一段代码:
   const int i=0;
   int *p=(int*)&i;
   p=100;
   通过强制类型转换,将地址赋给变量,再作修改即可以改变const常量值。
   8、请分清数值常量和指针常量,以下声明颇为玩味:
   int ii=0;
   const int i=0;            //i是常量,i的值不会被修改
   const int *p1i=&i;        //指针p1i所指内容是常量,可以不初始化
   int  * const p2i=ⅈ    //指针p2i是常量,所指内容可修改
   const int * const p3i=&i; //指针p3i是常量,所指内容也是常量
   p1i=ⅈ                  //合法
   *p2i=100;                //合法

   在好长一收段时间我被const困惑,看到const关键字,C++程序员首先想到的可能是const常量,如果只知道用const定义是常量,那么相当于把火药仅用于制作鞭炮。const更大的魅力是它可以修饰函数的参数、返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多C++程序设计书籍建议:"Use const whenever you need"。

二、const成员函数
    任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性。

以下程序中,类stack的成员函数GetCount仅用于计数,从逻辑上讲GetCount应当为const函数。编译器将指出GetCount函数中的错误。

[cpp]  view plain copy
  1. class Stack  
  2. {  
  3. private:  
  4.     int m_num;  
  5.     int m_data[100];  
  6. public:  
  7.     void Push(int elem);  
  8.     int Pop(void);  
  9.     int GetCount(voidconst;   //const成员函数  
  10. };  
  11.   
  12. int Stack::GetCount(voidconst  
  13. {  
  14.     ++m_num;   //编译错误,企图修改数据成员m_num  
  15.     Pop();     //编译错误,企图非const成员函数  
  16.     return m_num;  
  17. }  
const成员函数的声明看起来怪怪的:const关键字只能放在函数声明的尾部,大概是因为其它地方都已经被占用了。
<think> 首先,用户的问题是关于理解C语言中const修饰指针的几种情况。用户引用了三个参考资料,我需要从中提取相关信息来回答。 回顾用户的问题:"我想理解const修饰指针的几种情况 请问const修饰指针的几种情况的理解方法",并参考了三个引用: - 引用[1]: 讨论const修饰指针,提到如果指针可以修改指向的值,const可能没有意义,建议使用const修饰指针变量来解决问题。 - 引用[2]: 详细介绍了const修饰指针的三种情况,包括const修饰指针指向的内容、const修饰指针本身,以及两者都修饰,并提供了代码示例。 - 引用[3]: 解释了指针的修改行为,如修改指向地址或修改值。 用户的核心需求是理解const修饰指针的几种情况和学习方法。 从系统指令: - 所有行内数学表达式使用$...$格式(但这里没有数学内容,所以可能不适用)。 - 独立公式使用$$...$$格式(不适用)。 - LaTeX语法正确(重点在代码块)。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 结构清晰,逐步解决问题。 所以,我的回答结构应该是: 1. **清晰介绍const修饰指针的背景和意义**:解释为什么需要const修饰指针,以防止修改值或指针本身。 2. **详细解释几种情况**:基于引用[2],分为三种情况: a. const修饰指针指向的内容(指针可以指向不同地址,但不能修改值)。 b. const修饰指针本身(指针不能指向其他地址,但可以修改值)。 c. const修饰两者(都不能修改)。 3. **提供代码示例**:从引用[2]中提取或重构代码来展示每种情况。 4. **添加引用标识**:在解释末尾添加[^1], [^2], [^3] where appropriate。 5. **生成相关问题**:在结束时列出几个相关问题。 用户上次的问题是关于const修饰指针的,所以我需要确保回答连贯。 步骤: 1. **开头**:回答用户问题,解释const修饰指针的几种情况。 2. **主体**: - 情况1: const修饰指针指向的内容(const int *p 或 int const *p)。 - 情况2: const修饰指针本身(int * const p)。 - 情况3: const修饰两者(const int * const p)。 每种情况用代码块展示示例。 3. **结尾**:总结理解方法,比如记住const的位置决定修饰对象。 4. **生成相关问题**:例如: - const关键字在C语言中还有哪些用途? - 如何避免指针误修改数据? - 在实际编程中,什么时候使用const修饰指针? 确保代码块使用正确的格式: ```c // 代码示例 ``` 现在,构建回答: - **介绍**:在C语言中,const修饰指针用于限制指针的行为,防止意外修改数据或指针本身。理解const的修饰对象是关键,const可以修饰指针指向的内容或指针本身的指向。 - **情况1**:const修饰指针指向的内容。const int *p 或 int const *p;指针可以指向不同地址,但不能通过解引用修改值。 ```c int a = 50; const int *p = &a; // p可以指向不同地址,但不能修改a的值 p = &b; // 允许,修改指向 *p = 60; // 错误,不能修改值 ``` - **情况2**:const修饰指针本身。int * const p;指针不能指向其他地址,但可以修改值。 ```c int a = 50; int * const p = &a; // p不能指向其他地址 p = &b; // 错误,不能修改指向 *p = 60; // 允许,修改值 ``` - **情况3**:const修饰两者。const int * const p;都不能修改。 ```c int a = 50; const int * const p = &a; // 不能修改指向,也不能修改值 p = &b; // 错误 *p = 60; // 错误 ``` 引用标识:在适当地方添加[^1], [^2], [^3]。基于用户提供的引用: - 引用[1]讨论了const修饰指针的必要性。 - 引用[2]详细解释了三种情况。 - 引用[3]补充了指针修改行为。 所以在总结时添加引用。 最后,生成相关问题: 1. const修饰函数参数有什么作用? 2. 如何理解const在C语言中的内存保护机制? 3. const修饰指针在实际项目中的应用案例? </think> ### const修饰指针的几种情况的理解方法 在C语言中,`const`修饰指针用于限制指针的行为,防止意外修改数据或指针本身。理解的关键在于区分`const`修饰的是指针的指向(指针本身)还是指针指向的内容(值)。根据引用[2]的详细解释,结合其他引用,可以分为三种主要情况。下面我会逐步解释每种情况,并提供代码示例帮助你理解。理解方法是:**注意`const`关键字在声明中的位置——如果`const`出现在`*`左侧,修饰指针指向的内容;如果出现在`*`右侧,修饰指针本身;如果两侧都有,则修饰两者**[^2]。 #### 1. **`const`修饰指针指向的内容(不能修改值,指针可重新指向)** - **理解方法**:`const`限制通过解引用操作符(`*p`)修改值,但指针可以指向其他地址。声明形式为 `const int *p` 或 `int const *p`(两者等效)。这适用于需要保护数据不被意外修改的场景[^1][^2]。 - **代码示例**: ```c #include <stdio.h> int main() { int a = 50, b = 40; const int *p = &a; // const修饰*p(指向的内容),指针p可重新指向 // *p = 60; // 错误:不能修改值(编译报错) p = &b; // 正确:指针可指向新地址 printf("b的值: %d\n", *p); // 输出:40 return 0; } ``` - **关键点**:指针变量存储的地址可以改变,但指向的值不能被修改[^2][^3]。 #### 2. **`const`修饰指针本身(指针不能重新指向,值可修改)** - **理解方法**:`const`限制指针变量本身的指向(即不能指向新地址),但允许通过解引用修改值。声明形式为 `int * const p`。这适用于指针固定但内容可变的情况[^2][^3]。 - **代码示例**: ```c #include <stdio.h> int main() { int a = 50, b = 40; int * const p = &a; // const修饰p(指针本身),指向固定 *p = 60; // 正确:可以修改值 // p = &b; // 错误:不能修改指向(编译报错) printf("a的值: %d\n", a); // 输出:60 return 0; } ``` - **关键点**:指针的存储地址不能变,但指向的内容可以通过解引用修改[^2][^3]。 #### 3. **`const`同时修饰指针和指向的内容(两者都不能修改)** - **理解方法**:`const`既限制指针的指向,也限制值的修改。声明形式为 `const int * const p`。这提供了最强的保护,适用于只读数据[^1][^2]。 - **代码示例**: ```c #include <stdio.h> int main() { int a = 50, b = 40; const int * const p = &a; // const同时修饰p和*p // *p = 60; // 错误:不能修改值 // p = &b; // 错误:不能修改指向 printf("a的值: %d\n", *p); // 输出:50 return 0; } ``` - **关键点**:指针的指向和内容都被锁定,类似只读指针[^1][^2]。 #### 理解方法的总结 - **记忆口诀**:看`const`和`*`的相对位置: - `const`在`*`左边 → 修饰内容(值不可变)。 - `const`在`*`右边 → 修饰指针(指向不可变)。 - 两边同时有`const` → 两者都不可变[^2]。 - **常见错误**:如引用[1]提到,如果仅用`const int n;`但指针未修饰`const`,指针仍可能修改数据,导致`const`失效。因此,正确使用修饰指针变量才能确保数据安全[^1]。 - **实践建议**:在函数参数中使用`const`修饰指针,避免函数内部意外修改外部数据(例如 `void func(const int *p)`)[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值