• 『C语言进阶』const详解


    在这里插入图片描述
    🔥博客主页 小羊失眠啦
    🔖系列专栏 C语言Linux
    🌥️每日语录生活便是寻求新的知识。
    ❤️感谢大家点赞👍收藏⭐评论✍️


    在这里插入图片描述

    一、什么是const

    常类型,使用类型修饰符const说明的类型,常类型的变量或者对象的值是不能被更新的。

    const含义:只要一个变量前用const来修饰,就意味着该变量里的数据只能被访问,而不能被修改,也就是意味着“只读”(readonly)


    二、const的优点

    1. 定义常量:

      const int n=100;
      
      • 1
    2. 类型检查

      const常量与#define宏定义常量区别:

      • const定义变量类型只有整数或者枚举,并且常量表达初始化才为常量表达式

      • 预编译指令只是对进行简单的替换,不能进行类型检查,相比之下,被const修饰的变量有自己的类型,编译器可以通过安全检查

      • 其余情况下const常量只是一个被const限定的变量,不能与常量混肴

    3. 可以保护被修饰的东西,防止意外修改,增强程序的健壮性

    4. 可以避免不必要的内存分配,编译器通常不为被const修饰的变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。


    三、const的用法:

    3.1 修饰全局变量

    此时全局变量只能使用不可修改,直接修改(编译报错)与修改地址(程序异常)都不行

    #include 
    //const修饰全局变量
    //此时全局变量只能使用不可修改,直接修改(编译报错)与修改地址(程序异常)也不行
    const int a = 100;
    void test()
    {
        printf("a = %d\n", a);//直接使用
        //a = 200;//直接修改,编译报错,显示a是只读的
        //printf("a = %d\n", a);
        //int *p = &a;
        //*p = 300;//通过地址修改,程序异常,有些编译器可能只会显示警告,并不会报错,且程序能正常运行,但是不会显示任何结果
        //printf("a = %d\n", a);
    }
     
    int main()
    {
    	test();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    全局变量的作用域是整个文件,我们应该尽量避免使用全局变量,因为一旦有一个函数改变了全局变量的值,它也会影响到其他引用这个变量的函数,导致除了bug后很难发现,如果一定要用全局变量,我们应该尽量的使用const修饰符进行修饰,这样防止不必要的人为修改。

    3.2 修饰局部变量

    不可直接修改变量的值(编译报错),但是可以通过地址进行修改

    const int n = 5;
    int const n = 5;
    
    • 1
    • 2

    这两种写法是一样的,都是表示变量n的值不能被改变了,需要注意的是,用const修饰变量时,一定要给变量初始化,否则之后就不能再进行赋值了。

    #include
    //const修饰普通局部变量
    //不可直接修改(编译报错),但是可以通过地址进行修改
    void test()
    {
        const int b = 100;
        printf("b = %d\n", b);
        //b = 200;//直接修改,编译报错
        //printf("b = %d\n", b);
        int *p = &b;
        *p = 300;//通过地址进行修改
        printf("b = %d\n", b);
    }
    int main()
    {
    	test();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    接下来看看const用于修饰常量静态字符串,例如:

    const char* str = "fdsafdsa";
    
    • 1

    如果没有const的修饰,我们可能会在后面有意无意的写str[4]=’x’类似这样的语句,这样会导致对只读内存区域的赋值,然后程序会立刻异常终止。有了const,这个错误就能在程序被编译的时候就立即检查出来,这就是const的好处。让逻辑错误在编译期被发现。

    3.3 修饰指针变量的类型(即常量指针)

    const修饰指针变量的类型,可直接修改变量值,不可修改指针指向的地址里的内容(编译报错),可以修改指针的指向

    常量指针是指针指向的内容是常量,可以有以下两种定义方式:

    const int * n;
    int const * n;
    
    • 1
    • 2

    可以发现,无论是在int前还是在int后,const一直位于*之前

    #include
    void test()
    {
        int c = 100;
        const int *p = &c;
        printf("c = %d\n",c);
        c = 111;//可以直接修改变量的值
        printf("c = %d\n",c);
        //*p = 200;//不可修改指针指向的地址里的内容,编译报错
        //printf("c = %d\n",c);
        int d =300;
        p = &d;//可以修改指针的指向
        printf("*p = %d\n",*p);
    }
    int main()
    {
    	test();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.4 修饰指针变量(即指针常量)

    可以直接修改变量的值,可以修改指针指向地址的内容,但是不能修改指针的指向(编译报错)

    指针常量是指指针本身是个常量,不能在指向其他的地址,写法如下:

    int *const n;
    
    • 1
    #include
    void test()
    {
        int c = 200;
        int  * const p = &c;//const修饰指针,即指针常量
        printf("*p = %d\n",*p);
        c = 300;
        printf("c = %d\n",c);//直接修改值
        printf("*p = %d\n",*p);
        *p = 400;//修改指针指向地址里的内容
        printf("*p = %d\n",*p);
        int d =500;
        //p = &d;//不能修改指针的指向,编译报错
        //printf("*p = %d\n",*p);
    }
    int main()
    {
    	test();
    	return 0 ;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    区分常量指针和指针常量的关键就在于*的位置,以*为分界线,如果const在*的左边,则为常量指针,如果const在*的右边则为指针常量。

    如果我们将*读作‘指针’,将const读作‘常量’的话,内容正好符合:

    int const * n;
         常量+指针-->常量指针
    int *const n;
       指针+常量  -->常量指针
    
    • 1
    • 2
    • 3
    • 4

    3.5 指向常量的常指针

    是以上两种的结合,指针指向的位置不能改变并且也不能通过这个指针改变变量的值,但是依然可以通过其他的普通指针改变变量的值

    const int* const p;
    
    • 1
    #include
    void test()
    {
        int c = 200;
        const int * const p = &c;//即修饰指针变量类型又修饰指针变量
        printf("*p = %d\n",*p);
        c = 300;//可以直接修改值
        printf("c = %d\n",c);
        printf("*p = %d\n",*p);
        //*p = 400;//不能修改指针指向地址里的内容,编译报错
        //printf("*p = %d\n",*p);
        //int d =500;
        //p = &d;//不能修改指针指向,编译报错
        //printf("*p = %d\n",*p);
    }
    int main()
    {
    	test();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    四、修饰函数的参数

    根据常量指针与指针常量,const修饰函数的参数也是分为三种情况

    1. 防止修改指针指向的内容

      void StringCopy(char *strDestination, const char *strSource);
      
      • 1

      其中 strSource 是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图通过解引用的方式改动 strSource 的内容,编译器将指出错误。

    2. 防止修改指针指向的地址

      void swap ( int * const p1 , int * const p2 )
      
      • 1

      指针p1和指针p2指向的地址都不能修改。


    五、修饰函数的返回值

    如果给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
    例如函数

    const char * GetString(void)
    
    • 1

    如下语句将出现编译错误:

    char *str = GetString();
    
    • 1

    正确的用法是

    const char *str = GetString();
    
    • 1

    在这里插入图片描述

  • 相关阅读:
    [附源码]java毕业设计网上花店系统
    STM32 CAN总线通讯
    Maven快速学习
    链表动画演示 等比数列 linux视频等
    Mybatis save、saveOrUpdate、update的区别
    企业内网DNS搭建,SmartDNS,网站访问加速,解决dns污染等问题
    物联网亿万级通信一站式解决方案EMQ
    Java学习禁忌
    使用终端MobaXterm连接Centos
    我的第一个Spring Boot应用实现步骤以及遇到的问题
  • 原文地址:https://blog.csdn.net/hsjsiwkwm/article/details/133784185