1.知识点
1.1指针常量——指针类型的常量
(1)指针常量本质是常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。
(2)在指针常量中,指针的值不可变,即始终指向同一个地址。
(3)但指针所指向的地址的值是可以通过*p来改变的。
用法如下:
1 //技巧: 2 //(1)读法:从左到右读,前面的是修饰词,后面的是主语 3 //如先出现指针(*),后出现常量(const),所以是指针常量 4 //(2)哪个东西不可变:直接看const后边是什么就什么不可变 5 //const后边是指针(p),所以是指针本身的值不可变。 6 int a = 10, b = 20; 7 int * const p = &a; 8 *p = 30;
1.2常量指针——指向常量的指针
(1)常量指针本质上是一个指针,常量表示指针指向的内容,说明指针指向的是一个“常量”。
(2)在常量指针中,指针指向的内容是不可变的,不可以通过*p来改变,但变量(指针指向的地址)可以通过自身赋值改变。
(3)另指针指向的地址是可以变的,即指向其他地址。
用法如下:
1 //技巧: 2 //(1)读法:从左到右读,前面的是修饰词,后面的是主语 3 //如下先出现常量(const),然后出现指针(*),所以是常量指针 4 //(2)哪个东西不可变:直接看const后边是什么就什么不可变 5 //如下const后面是*p,所以是指针指向的地址的值不可变(只限定了不可以通过*p来改变) 6 int a = 10, b = 20; 7 int const *p = &a;//不可以通过*p改变a的值 8 p = &b;//指针的地址是可以变的 9 a = 30;//也可以通过变量本身改变值
1.3const int 与int consts是等价的
const int *p==int const *p
2.面试题
2.1指针常量和常量指针的常见错误
1 int main(int argc, char *argv[]) { 2 int m = 10; 3 const int n = 20; 4 5 const int *ptr1 = &m; 6 int * const ptr2 = &m; 7 8 ptr1 = &n; 9 ptr2 = &n; 10 11 *ptr1 = 3; 12 *ptr2 = 4; 13 14 int *ptr3 = &n; 15 const int *ptr4 = &n; 16 17 int *const ptr5; 18 ptr5 = &m; 19 20 const int * const ptr6 = &m; 21 *ptr6 = 5; 22 ptr6 = &n; 23 24 getchar(); 25 return 0; 26 }
答案解析:
1 int main(int argc, char *argv[]) { 2 int m = 10; //正确,变量 3 const int n = 20; //正确,常量 4 5 const int *ptr1 = &m; //正确,常量指针,指向的地址的内容不可变 6 int * const ptr2 = &m; //正确,指针常量,指针指向不可变,是常量所以必须赋初值 7 8 ptr1 = &n;//正确 9 ptr2 = &n;//错误,指针常量,指针的指向不可变 10 11 *ptr1 = 3;//错误,常量指针,指针指向的地址的内容不可变 12 *ptr2 = 4;//正确 13 14 int *ptr3 = &n;//错误,不能将常量的地址赋值给普通指针,常量地址只能赋值给常量指针 15 const int *ptr4 = &n;//正确 16 17 int *const ptr5;//错误,指针常量是常量,所有常量在定义时都必须赋初值 18 ptr5 = &m;//错误,应该定义时直接赋初值 19 20 const int * const ptr6 = &m;//正确,同时包含指针常量和常量指针的性质 21 *ptr6 = 5;//错误,不符合常量指针的性质 22 ptr6 = &n;//错误,不符合指针常量的性质 23 getchar(); 24 return 0; 25 }
2.2指针常量用作函数参数
写出程序的输出结果,并说明在函数exchange2中将参数声明为const的意义,是否可以将const修饰符放在*之前。
1 void exchange1(int a, int b) { 2 int temp = a; 3 a = b; 4 b = temp; 5 } 6 void exchange2(int * const a, int * const b) { 7 int temp = *a; 8 *a = *b; 9 *b = temp; 10 } 11 int main(int argc, char *argv[]) { 12 int m = 10, n = 20; 13 exchange1(m, n); 14 cout << "m=" << m << ";n=" << n << endl; //输出:m=10;n=20 15 exchange2(&m, &n); 16 cout << "m=" << m << ";n=" << n << endl; //输出:m=20,n=10 17 getchar(); 18 return 0; 19 }
答案:第一行输出的是:m=10,n=20;第二行输出是:m=20,n=10.
解析:exchange1按值传递,函数中a,b值交换与m,n无任何联系,故无法改变m,n的值;exchange2中传入m,n的地址,通过解引用可以在函数内部改变m,n的值。在函数exhange2的参数中,const的作用是将指针声明为指针常量,防止指针a和b在使用过程中意外发生改变(改变将会报错)。如果将const放在*之前,指针a和b变成常量指针,无法修改指针指向的内容,从而无法实现交换m和n的目的。
2.3指针常量和字符串常量的冲突
请写出下面程序的运行结果:
1 int main(){ 2 char *const str="apple"; 3 *str="orange"; 4 cout<<str<<endl; 5 getchar(); 6 return 0; 7 }
答案1(其实有问题,看下面说明,):
int main(){ char *const str="apple"; //错误,为了修改str的值应该去掉const *str="orange";//错误,根据字符串赋值规则应该改为str="orange" cout<<str<<endl; getchar(); return 0; }
说明:(1)一个字符串返回的是首字母的地址,故*str的值为'a'.
(2)字符串常量是存储在常量区,而常量的值不可以修改,所以在VC编译器中下面的语句是编译不过去的
char *str = "apple";
最正确的语句应该是(因为字符串常量本身是常量,不应该赋值给一个普通指针,这意味着通过指针可以改变常量的值,前后矛盾,上面语句在一些地方能通过编译,其实是由于历史遗留问题):
const char *str = "apple";
(3)字符串正确赋值给变量应该是给str,因为字符串返回的其实是字符串的首地址,所以应该赋值给指针str,而不是*str,该指针指向首地址。
综上最正确的答案应该如下:
1 int main(){ 2 const char *str = "apple";//常量指针,指向的内容不可变 3 str = "oragne";//指针的指向是可变的 4 cout<<str<<endl; 5 getchar(); 6 return 0; 7 }