美文网首页C语言C语言&嵌入式
C语言const关键字到底怎么用

C语言const关键字到底怎么用

作者: 程序猿编码 | 来源:发表于2020-04-15 19:30 被阅读0次

    前言

    作为C/C++开发人员,我们看到关键字const时,第一反应就说它就是:只读。const要求其所修饰的对象为常量。不可对其修改和二次赋值操作(不能作为左值出现)。本文说明C中的const关键字,不包括C++。

    const基本介绍

    const是constant的简写,可以理解成是”只读变量“的限定词,从这里可以看出,const修饰的是变量,跟常量是不同的,常量是被编译器放在内存中的只读区域,当然也就不能够去修改它。

    而”只读变量“则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改。

    const就是用来限定一个变量不允许被改变的修饰符。因为const声明的变量是只读变量。

    用const修饰普通变量

    例如:

    const int NUM = 10; //与int const NUM等价
    NUM = 12;  //编译错误,不可再次修改
    

    以上代码中的const告诉编译器,const修饰NUM是只读,不可以被修改。如果在函数中不小心使用类似二次赋值操作,编译器会捕获这个错误,并生成一条错误的信息。类似提示向只读变量‘NUM’赋值:

    这里要注意一下

    如果需要使用const修饰一个变量,那么它只能在开始声明时就赋值,否则后面就没有机会了。

    修饰数组

    #include <stdio.h>
    
    int sum( int arr[],int n);
    
    int main(int argc, char const *argv[])
    {
         int arr[] = {0,0,2,3,4}; //
    
        arr[2] = 1; // 0 + 0 +1 + 3 + 4
    
        int value = sum(arr,5);
    
        printf("ar value: %d\n",value); // 8
    
    
        return 0;
    }
    
    
    int sum( int arr[],int n){
    
        int i;
        int total = 0;
    
        for (i = 0; i < n; i++){
            total += arr[i];
        }
    
        return total;
    }
    

    编译运行:

    编译运行一点问题都没有,如果使用const关键字修饰数组,使其元素不允许被改变。

    const int arr[] = {0,0,2,3,4}; //与int const arr[]等价
    arr[2] = 1; //编译错误
    

    试图修改arr的内容的操作是非法的,编译器将会报错:

    修饰指针

    修饰指针的情况比较多,主要有以下几种情况。

    1.const 修饰 *p,指向的对象只读,指针的指向可变:

    int a = 10;
    int b = 12;
    const int *p = &a;//p是一个指向int类型的const值,与int const *p等价
    *p = 11;    //编译错误,指向的对象是只读的,不可通过p进行改变
    p = &b;     //合法,改变了p的指向
    

    const int* p; 这是修饰了谁呢?

    其实我们可以这样想,如果我们把int 拿出来 也就是 const int (p); 等价于 int const (p);

    由此我们可以看出来const修饰了p啊! 也就是指向的内容不可以改变,比如p已经指向a变量,但是p=11;会报错,因为*p不可改变 但是地址是可以改变的。

    比如b=12, p=&b;是正确的,因为改变了p的指向。

    2.const修饰p,指向的对象可变,指针的指向不可变:

    int a = 10;
    int b = 12;
    int * const p = &a;//p是一个const指针
    *p = 11;    //合法,
    p = &b;     //编译错误,p是一个const指针,只读,不可变
    

    3.指针不可改变指向,指向的内容也不可变:

    int a = 10;
    int b = 12;
    const int * const p = &a;//p既是一个const指针,同时也指向了int类型的const值
    *p = 11;    //编译错误,指向的对象是只读的,不可通过p进行改变
    p = &b;     //编译错误,p是一个const指针,只读,不可变
    

    看完上面几种情况之后是否会觉得混乱,并且难以记忆呢?我们使用一句话总结:

    const放在的左侧任意位置,限定了该指针指向的对象是只读的;const放在的右侧,限定了指针本身是只读的,即不可变的。

    如果还不能很好的理解,可以去掉类型说明符,例如:

    const *p; //修饰*p,指针指向的对象不可变
    * const p; //修饰p,指针不可变
    const * const p; //第一个修饰了*p,第二个修饰了p,两者都不可变
    

    库函数中const怎么用呢!

    实际上,为我们可以经常发现const关键字的身影,例如很多库函数的声明:

    #include <string.h>
    int strncmp(const char *s1, const char *s2, size_t n);
    void *memmove(void *s1, const void *s2, size_t n);
    har *strncpy(char *restrict s1, const char *restrict s2, size_t n);
    

    通过看strncmp函数的原型可以知道,源字符串s2是只读的,不可变的,而s1并没有该限制。

    修饰全局变量

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

    test1.c
    定义一些全局变量。

    const doubule PI = 3.141;
    

    test2.c
    使用在其他文件中定义的全局变量。

    extern const double PI;
    

    其次是将常量放在一个include文件中。这时还必须使用静态外部存储类:

    constant.h
    定义一些全局变量。

    static const double PI = 3.141;
    
    /*test1.c——使用在其他文件中定义的全局变量*/
    
    #include "constant.h"
    
    /*test2.c——使用在其他文件中定义的全局变量*/
    
    #include "constant.h"
    

    如果不使用关键字static,在文件test1.c和test2.c中包含constant.h将导致每个文件都有统一标示符的定义声明。导致编译会出现重复定义的错误。

    修饰函数的返回值

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

    const char * GetString();
    

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

    char *str = GetString();
    

    正确的用法是:

    const char *str = GetString();
    

    总结

    借助上面理解,就会发现以下几种等价情况:

    const int NUM = 11; //与int const NUM等价
    int a = 12;
    const int *p = &a;//与int const *p等价
    const int arr[] = {0,7,2,3,4}; //与int const arr[]等价

    const 的好处是引入了常量的概念,让我们不要去修改不该修改的内存。直接的作用就是让更多的逻辑错误在编译期被发现。

    程序猿编码

    欢迎关注公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。或者回复:进入技术交流群。网盘资料有如下:

    欢迎领取:百度网盘资料

    相关文章

      网友评论

        本文标题:C语言const关键字到底怎么用

        本文链接:https://www.haomeiwen.com/subject/noshvhtx.html