zoukankan      html  css  js  c++  java
  • 第9课

    第9课 - const和volatile分析

    1. const只读变量

    (1)const修饰的变量是只读的,本质上还是变量,并不是真正意义上的常量         ※ const只是告诉编译器该变量不能出现在赋值符号的左边

    (2)const修饰的局部变量在栈上分配空间;const修饰的全局变量在全局数据区分配空间

    (3)const只在编译期间有用(检查const修饰的变量有没有出现在赋值符号左边,如果有就会编译报错),在运行期间无用

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     const int cc = 1;
     6 
     7     int *p = (int*)&cc;
     8 
     9     // cc = 10;  // compile error: assignment of read-only variable ‘cc’
    10 
    11     printf("cc = %d
    ", cc);    // cc = 1
    12 
    13     *p = 10;
    14 
    15     printf("cc = %d
    ", cc);    // cc = 10
    16 
    17     return 0;
    18 }

    2. const全局变量的分歧

    (1)在标准C语言编译器中,const修饰的全局变量仍然存储于全局数据区,并没有改变存储方式,通过指针可以隐式的修改全局变量的值。

    (2)在现代C语言编译器中,将const 修饰的全局变量分配在只读存储区,改变了存储方式,通过指针隐式修改会导致程序段错误

     1 #include <stdio.h>
     2 
     3 const int g_ci = 100;
     4 
     5 int main()
     6 {
     7     int *p = (int *)&g_ci;
     8 
     9     // g_ci = 10; // compile error: assignment of read-only variable ‘g_ci’
    10 
    11     printf("g_ci = %d
    ", g_ci);
    12 
    13     *p = 10;    // 通过指针隐式修改
    14 
    15     printf("g_ci = %d
    ", g_ci);
    16 
    17     return 0;
    18 }

    使用gcc编译执行(现代C编译器)    ==>    段错误

      

    使用bcc32编译执行(标准C编译器)  ==>    修改成功

      

    3. const的本质

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

    (2)现代C编译器中的const将具有全局生命周期的变量(全局变量 +  static修饰的局部变量)存储于只读存储区

              

    【static修饰局部变量】

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     const static int si = 100;  // const修饰static修饰的局部变量
     6 
     7     int *p = (int *)&si;
     8 
     9     *p = 1;    // 使用gcc、VS2010编译执行会产生段错误
    10                // 使用bcc32编译执行,可以修改si的值为1
    11 
    12     printf("si = %d
    ", si);
    13 
    14     return 0;
    15 }

    【const的本质分析】

     1 #include <stdio.h>
     2 
     3 const int g_array[5] = {0};
     4 
     5 void modify(int* p, int v)
     6 {
     7     *p = v;
     8 }
     9 
    10 int main()
    11 {
    12     int const i = 0;  // const放在int前后都可以
    13     const static int j = 0;
    14     int const array[5] = {0};
    15     
    16     modify((int*)&i, 1);           // ok
    17     modify((int*)&j, 2);           // error,j存储在只读存储区
    18     modify((int*)&array[0], 3);    // ok
    19     modify((int*)&g_array[0], 4);  // error,g_array[5]数组存储在只读存储区
    20     
    21     printf("i = %d
    ", i);
    22     printf("j = %d
    ", j);
    23     printf("array[0] = %d
    ", array[0]);
    24     printf("g_array[0] = %d
    ", g_array[0]);
    25     
    26     return 0;
    27 }

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

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

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

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

          

    【const修饰函数参数与返回值】

     1 #include <stdio.h>
     2 
     3 const char* f(const int i)
     4 {
     5     // i = 5;  // error, i不能作为左值
     6     
     7     return "swj striving! 2019-12-23 22:23:57";
     8 }
     9 
    10 int main()
    11 {
    12     char* pc = f(0); // 编译会报warning,函数f的返回值为const char*
    13     
    14     printf("%s
    ", pc);
    15     
    16     pc[1] = '_';    // error,试图修改只读存储区中的字符串
    17     
    18     printf("%s
    ", pc);
    19     
    20     return 0;
    21 }

    5. 深藏不露的volatile

    (1)volatile 可理解为 "编译器警告指示字"

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

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

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

     

    6. 有趣的问题

      const  volatile int i  =  0;

      ⅰ:变量 i 具有什么样的特性?   i为int型变量,每次都必须到内存取值,且i是只读变量

      ⅱ:编译器如何处理这个变量?  i不能作为左值

  • 相关阅读:
    图书管理系统
    关键路径
    最短路径

    最小生成树、最短路径
    Huffman编码
    LA 3401
    UVA 10881
    OI 刷题记录——每周更新
    4396: [Usaco2015 dec]High Card Wins
  • 原文地址:https://www.cnblogs.com/shiwenjie/p/11853892.html
Copyright © 2011-2022 走看看