zoukankan      html  css  js  c++  java
  • (转载)C++常量折叠和C语言中const常量对比

    (转载)http://www.360doc.com/content/12/0824/20/8093902_232153101.shtml
    #include <iostream>
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
      const int a = 10;
      int *p = (int *) &a;//让p指向与a相同的内存空间
      cout << *p << " " << a << endl;
      cout << p << " " << &p << endl;
      *p = 20;// 照里说a的值也应该改变,实际却没有,这就是常量折叠.
    
      cout << *p << " " << a << endl;
      cout << p << " " << &p << endl;
    
    
        // 这个"常量折叠"就是在编译器进行语法分析的时候,将常量表达式计算求值,
    
       // 并用求得的值来替换表达式,放入常量表。可以算作一种编译优化。
    
       // 我只是改了这个地址内容,但是a还是,
    
        // 因为编译器在优化的过程中,会把碰见的const全部以内容替换掉
    
       // (跟宏似的: #define PI 3.1415,用到PI时就用.1415代替),
    
       // 这个出现在预编译阶段;但是在运行阶段,它的内存里存的东西确实改变了!(下面演示)
    
      return 0;
    }


    输出结果:
    10 10

    0xbfda9ccc 0xbfda9cc8
    20 10
    0xbfda9ccc 0xbfda9cc8

    为了验证在运行阶段,a所在地址的内容确实被*p = 20改变了,我们单步调试如下:

    Reading symbols from /home/beijibing/zixue/unp2/svshm/test...done.

    (gdb) b 9

    Breakpoint 1 at 0x80487e7: file test.c, line 9.

    (gdb) run

    Starting program: /home/beijibing/zixue/unp2/svshm/test 

    10 10

    0xbffff39c 0xbffff398 // 前两个cout输出后,我们知道了存a和p的堆栈地址。

    Breakpoint 1, main (argc=1, argv=0xbffff454) at test.c:9

    9  *p = 20;   //在这里设了断点,先暂停查看现在堆栈内容

    (gdb) x/2x 0xbffff398 //从低地址查看2个字的内容

    0xbffff398: 0xbffff39c 0x0000000a   //可以看出0xbffff398中存放的是a的地址0xbffff39c,而0xbffff39c中存放的是0xa(10进制为10)

    (gdb) n

    11  cout << *p << " " << a << endl;

    (gdb) x/2x 0xbffff398

    0xbffff398: 0xbffff39c 0x00000014     //单步执行后在查看,发现0xbffff39c中的值被改为0x14(20),正如上面所述

    (gdb) n

    20 10

    12  cout << p << " " << &p << endl;

    (gdb) n

    0xbffff39c 0xbffff398

    19  return 0;

    (gdb) 

     

     

    总结:编译器会为常量分配了地址,但是在使用常量的时候,常量会被一立即数替换(保护常量,防止被破坏性修改)

    在C++中对于基本类型的常量,编绎器并不为其分配存储空间,编译器会把它放到符号表,当取符号常量的地址等操作时,将强迫编译器为这些常量分配存储空间,编译器会重新在内存中创建一个它的拷贝,通过地址访问到的就是这个拷贝而非原始的符号常量。

     

    和C语言中const常量对比:

     

    #include <stdio.h>
    
    int main()
    {
      const int a = 10;
      int *p = (int *) &a;
      printf("%d, %d\n",*p,a) ;
      printf("%x, %x\n",p,&p) ;
    
      *p = 20;
     // a = 30;  //常量是不能修改的,error: assignment of read-only variable 'a’
    
      printf("%d, %d\n",*p,a) ;
       printf("%x, %x\n",p,&p) ;
    
      return 0;
    }

     

     

     

    编译运行结果:

    10, 10

    bfea80fc, bfea80f8

    20, 20

    bfea80fc, bfea80f8

    可以查看二进制文件,发现a并没有在链接的时候占用.rodata空间。

    注意:可以看出a被修改了,a是在栈上分配的常量,a本身不能修改,但是可以用指针p指向a,然后修改p指向的内容,这样就可以修改常量a的内容了。
  • 相关阅读:
    Linux内核网络协议栈优化总纲
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 判断字符位置
    Java实现 蓝桥杯VIP 算法训练 判断字符位置
    Java实现 蓝桥杯VIP 算法训练 链表数据求和操作
  • 原文地址:https://www.cnblogs.com/Robotke1/p/3080377.html
Copyright © 2011-2022 走看看