• 指针和引用(2)指针常量与常量指针


    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  }
  • 相关阅读:
    ThinkPHP的ajaxReturn方法的使用
    PHP中如何获取网站根目录物理路径
    MySQL索引覆盖
    php对gzip的使用(实例)
    php对gzip的使用(开启)
    php对gzip的使用(理论)
    ThinkPHP中调用PHPExcel
    PHPExcel正确读取excel表格时间单元格(转载)
    Kubernetes pod网络解析
    vRO 添加已有磁盘到VM
  • 原文地址:https://www.cnblogs.com/ys99/p/9194936.html
Copyright © 2020-2023  润新知