zoukankan      html  css  js  c++  java
  • 6 const 和 volatile

    1 const 定义一个只读变量,而不是常量

    • const 修饰的变量是只读的,其本质还是变量

      const 修饰的变量不是真正的常量,它只是告诉编译器该变量不能出现在赋值符号的左边

    • const 修饰的局部变量上分配空间;const 修饰的全局变量全局数据区分配空间,所以 const 修饰的变量在内存中是分配了空间的,那么就可以修改这个空间里的值

    • const 只在编译期对编译器有用,在运行期无用,即可以修改所修饰的变量的值

    2 const 全局变量的分歧

    • 现代C语言编译器中,const 全局变量存储于只读存储区,修改 const 全局变量将导致程序崩溃

    • 标准C语言编译器中不会将 const 修饰的全局变量存储于只读存储区,而是存储于可修改的全局数据区,所以其值可以改变

    • 示例1:const 修饰局部变量 => read-only variable,不可直接修改

      • Demo

        #include <stdio.h>
        
        int main()
        {
            //const修饰的局部变量,即所谓的“常量”
            const int cc = 1;
            printf("cc = %d
        ",cc);
            
            cc = 3;
            printf("cc = %d
        ",cc);
            
            return 0;
        }
        
      • GCC 编译

        test1.c: In function 'main':
        test1.c:9: error: assignment of read-only variable 'cc'
        
    • 示例2:const 修饰局部变量,可利用指针修改

      • Demo

        #include <stdio.h>
        
        int main()
        {
            //const修饰的局部变量,即所谓的“常量”
            const int cc = 1;
            int* p = (int*)&cc;
            printf("cc = %d
        ",cc);
            
            *p = 3;
            printf("cc = %d
        ",cc);
            
            return 0;
        }
        
      • GCC 编译

        cc = 1
        cc = 3
        
    • 示例3:const 修饰全局变量,read-only variable

      • Demo

        #include <stdio.h>
        
        //const 修饰全局变量
        const int g_cc = 2;
        
        int main()
        {
            printf("g_cc = %d
        ",g_cc);
            
            g_cc = 4;
            printf("g_cc = %d
        ",g_cc);
            
            return 0;
        }
        
      • GCC 编译

        test3.c: In function 'main':
        test3.c:10: error: assignment of read-only variable 'g_cc'
        
    • 示例4:利用指针修改 const 修饰的全局变量

      • Demo

        #include <stdio.h>
        
        //const 修饰全局变量
        const int g_cc = 2;
        
        int main()
        {
            printf("g_cc = %d
        ",g_cc);
            
            int* p = (int*)&g_cc;
            
            *p = 4;
            printf("g_cc = %d
        ",g_cc);
            
            return 0;
        }
        
      • GCC 编译通过,运行出错!

        g_cc = 2
        段错误
        
      • BCC 运行

        g_cc = 2
        g_cc = 4
        

    3 const 的本质

    • C语言中的 const 使得变量具有只读属性

    • 现代C编译器中 const具有全局生命周期的变量(全局生命周期的变量有:全局变量,static 修饰的局部变量)存储于只读存储区,其值不可改变

    • const 不能定义真正意义上的常量,只是一个只读变量

    • 示例5:修改被 const 修饰的具有全局生命周期的变量

      • Demo

        #include <stdio.h>
        
        //const 修饰的普通全局数组,其中每个元素都为只读变量
        const int g_array[5] = {0};
        
        void modify(int* p,int v)
        {
            *p = v;
        }
        
        int main()
        {
            const int i = 0;  // const 修饰的普通局部变量
            const static int j = 0;  // const 修饰的 static 局部变量
            const int array[5] = {0};  // const修饰的普通局部数组
            
            modify((int*)&i,1);  // ok
            modify((int*)&j,2);  // error
            modify((int*)&array[0],3);  // ok
            modify((int*)&g_array[0],4);  // error
            
            printf("i = %d
        ",i);
            printf("j = %d
        ",j);
            printf("array[0] = %d
        ",array[0]);
            printf("g_array[0] = %d
        ",g_array[0]);
            
            return 0;
        }
        
      • 编译运行

        段错误
        
      • 注释18,20行

        #include <stdio.h>
        
        //const 修饰的普通全局数组,其中每个元素都为只读变量
        const int g_array[5] = {0};
        
        void modify(int* p,int v)
        {
            *p = v;
        }
        
        int main()
        {
            const int i = 0;  // const 修饰的普通局部变量
            const static int j = 0;  // const 修饰的 static 局部变量
            const int array[5] = {0};  // const修饰的普通局部数组
            
            modify((int*)&i,1);  // ok
            //modify((int*)&j,2);  // error
            modify((int*)&array[0],3);  // ok
            //modify((int*)&g_array[0],4);  // error
            
            printf("i = %d
        ",i);
            printf("j = %d
        ",j);
            printf("array[0] = %d
        ",array[0]);
            printf("g_array[0] = %d
        ",g_array[0]);
            
            return 0;
        }
        
      • 编译运行

        i = 1
        j = 0
        array[0] = 3
        g_array[0] = 0
        

    4 const 修饰函数参数和返回值

    • const 修饰函数参数表示在函数体内不希望改变参数的值

    • const 修饰函数返回值表示返回值不可改变,多用于返回指针的情形

    • C 语言中的字符串字面量存储于只读存储区中,在程序中需要使用 const char* 指针来指向

    • 示例:字符串字面量

      • Demo1:利用 char* 指向一个字符串字面量,错误行为!

        #include <stdio.h>
        
        const char* f(const int i)
        {
            i = 5;  //error
            return "ABCD EFG";
        }
        
        int main()
        {
            char* pc = f(0);
            
            printf("%s
        ",pc);
            
            pc[4] = '_';
            
            printf("%s
        ",pc);
            
            return 0;
        }
        
      • 编译

        test.c: In function 'f':
        test.c:5: error: assifnment of read-only location 'i'
        test.c: In fuction 'main':
        test.c:11: warning: initialization discards qualifiers from pointer target type
        
      • Demo2

        #include <stdio.h>
        
        const char* f(const int i)
        {
            return "ABCD EFG";
        }
        
        int main()
        {
            char* pc = f(0);
            
            printf("%s
        ",pc);
            
            pc[4] = '_';
            
            printf("%s
        ",pc);
            
            return 0;
        }
        
      • 编译

        test.c: In fuction 'main':
        test.c:11: warning: initialization discards qualifiers from pointer target type
        
      • 运行

        ABCD EFG
        段错误
        
      • Demo3:利用 const char* 接收函数的返回值,不可修改

        #include <stdio.h>
        
        const char* f(const int i)
        {
            return "ABCD EFG";
        }
        
        int main()
        {
            const char* pc = f(0);
            
            printf("%s
        ",pc);
            
            pc[4] = '_';
            
            printf("%s
        ",pc);
            
            return 0;
        }
        
      • 编译

        test.c: In fuction 'main':
        test.c:14: error: assignment of read-only location '*(pc+4u)'
        

    5 volatile 关键字

    • volatile 可理解为“编译器警告指示字”

    • volatile 告诉编译器必须每次去内存中取变量值

    • volatile 主要修饰可能被多个线程访问的变量

    • volatile 也可以修饰可能被未知因数更改的变量

    • 示例

      • 编译器在编译的时候发现 obj 没有被当作左值使用,因此会直接将 obj 替换成 10,而把 a 和 b 都赋值为 10
      • 如果暂停 100ms,在这段时间内很可能 obj 变量这段内存空间很可能被线程所改变,那么 b 所得到的值就不应该是 10 了
      • 这种情况下,应该用 volatile 修饰 obj 变量
      int obj = 10;
      
      int a = 0;
      int b = 0;
      
      a = obj;
      
      sleep(100);
      
      b = obj;
      
  • 相关阅读:
    云中树莓派(5):利用 AWS IoT Greengrass 进行 IoT 边缘计算
    乐观锁 与 悲观锁 来解决数据库并发问题
    Python二维数组构造
    一次问题追查----短字符串签名算法引发的bug
    C++ assert 断言使用
    并查集(Union-Find)算法
    linux shell grep/awk/sed 匹配tab
    C++ 变量默认初始值不确定(代码测试)
    linux 查看机器内存方法 (free命令)
    html table奇偶行颜色设置 (CSS选择器)
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13598584.html
Copyright © 2011-2022 走看看