美文网首页
C/C++:Const总结

C/C++:Const总结

作者: Sivin | 来源:发表于2020-05-11 01:20 被阅读0次

    指针变量和它所指向的内存空间是两个不同的概念

    由于Const在C和C++中存在差异,本篇将会对Const在两种语言的表现异同点上进行对比探讨。

    实现方式不同

    在C语言中,Const修饰的变量只是告诉编译器该变量是一个只读的变量,不能通过该变量改写器内存空间中的值,但是其本质上还是一个变量,既然是变量,就会有内存地址,因此可以通过指针间接修改该地址空间的值。

    const int a = 10;
    int* p = &a;
    *p = 20;
    printf("a = %d, *p = %d\n", a, *p);
    -------------结果------------------
    a = 20, *p = 20
    

    在C++中Const修饰的变量被称为常量,其值存放在常量表中,在使用常量时,编译器回到常量表中查询对应的常量,并将其替换,这部分没有涉及内存分配,因此对其取地址是没有意义的。但是当我们非要对该常量去地址时,则编译器会为其临时分配一个内存,并将常量值存入该临时内存中,事实上,在C++中规定必须用const修饰的指针来指向const修饰的常量。虽然可以使用强制转换的方式,对Const修饰的常量进行去地址,并将其赋值给一个非Const修饰的指针(最好不要这样做),但打这个指针上的任何改动都只会影响到临时分配的内存空间,而不会影响到原常量上。

    const int a = 10;
    int* p = (int *)&a;
    *p = 20;
    printf("a = %d, *p = %d\n", a, *p);
    -------------结果------------------
    a = 10, *p = 20
    

    变量的文件作用域

    在C语言中,访问一个变量之前,该变量必须要被预先定义,当访问一个由外部文件定义的变量时,则必须要提前声明该变量。来看下面几个例子。

    // main.c
    extern int a;
    int main() {
        printf("a = %d\n", a);
        return 0;
    }
    //ln_const.c
    int a = 128;
    --------结果-------
    a = 128
    

    上面的例子是一个标准C语言访问外部变量的例子。我们编写代码时也应该遵守这样的规则。但是,总有写人不是那么规范,例如可以在main.c文件中将extern关键字去掉。

    // main.c
    int a;
    int main() {
        printf("a = %d\n", a);
        return 0;
    }
    //ln_const.c
    int a = 128;
    --------结果-------
    a = 128
    

    我们发现实际上结果并没有变化,因为编译器在编译时,如果在当前文件中该变量没有被定义,则会从其他文件中寻找定义并链接。因此结果是没有问题的。那么如果变量a的定义被设定成文件内私有时,将会发生什么呢?

    // main.c
    int a;
    int main() {
        printf("a = %d\n", a);
        return 0;
    }
    // ln_const.c
    static int a = 128;
    --------结果-------
    a = 0
    

    发生这种现象的原因是,编译器没有找到该变量的外部定义,则直接将声明默认为定义,因此变量a是一个默认赋值。事实上extern关键字的作用就是,告诉编译器,该变量的值是由外部文件定义的。因此当我们声明一个外部变量时,如果编译器无法再外部找到该变量的定义,则会无法编译通过。

    // main.c
    extern int a;
    int main() {
        printf("a = %d\n", a);
        return 0;
    }
    // ln_const.c
    static int a = 128;
    --------结果-------
    编译失败,无法解析外部符号a
    

    那么如果我们在外部定义了一个Const变量,情况是否会有不同呢?在标准情况下,声明和定义,应该是保持一致的。因此标准做法应该是这样的。

    // main.c
    extern const int a ;
    int main() {
        printf("a = %d\n", a);
        return 0;
    }
    
    // ln_const.c
    const int a = 128;
    -----结果---------
    a = 128
    

    C语言的难点之一就是规范标准,总有人会在声明时忘记const关键字,但是结果也是正确的。

    // main.c
    extern int a ;
    int main() {
        printf("a = %d\n", a);
        return 0;
    }
    
    // ln_const.c
    const int a = 128;
    -----结果---------
    a = 128
    

    既然a在声明时并没有Const修饰是不是意味着,可以直接修改a呢?

    // main.c
    extern int a ;
    int main() {
        a = 20;
        printf("a = %d\n", a);
        return 0;
    }
    
    // ln_const.c
    const int a = 128;
    -----结果---------
    编译失败,运行时异常
    

    这里,我们可以看出,变量的声明帮助编译器进行语法检查,但变量的定义决定了运行时的行为。

    static关键字和Const关键字同时修饰变量时,Const是否会修改变量的文件作用域呢?

    // main.c
    extern int a ;
    int main() {
        printf("a = %d\n", a);
        return 0;
    }
    
    // ln_const.c
    static const int a = 128;
    -----结果---------
    编译失败,无法解析外部符号a
    

    总结:在C语言中,变量文件作用域一般都是外部链接,除非使用static关键字修饰,Const关键字并不会改变变量的文件作用域

    相关文章

      网友评论

          本文标题:C/C++:Const总结

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