小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

C++ 常量折疊和C語言中const常量對比

 幸福的樂土 2012-08-24

#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
  const int a = 10;
  int *p = (int *) &a;//p指向與a相同的內(nèi)存空間
  cout << *p << " " << a << endl;
  cout << p << " " << &p << endl;
  *p = 20;// 照里說a的值也應該改變,實際卻沒有,這就是常量折疊.

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

// 這個"常量折疊"就是在編譯器進行語法分析的時候,將常量表達式計算求值,

    // 并用求得的值來替換表達式,放入常量表??梢运阕饕环N編譯優(yōu)化。

    // 我只是改了這個地址內(nèi)容,但是a還是,

    // 因為編譯器在優(yōu)化的過程中,會把碰見的const全部以內(nèi)容替換掉

    // (跟宏似的: #define PI 3.1415,用到PI時就用.1415代替),

    // 這個出現(xiàn)在預編譯階段;但是在運行階段,它的內(nèi)存里存的東西確實改變了!(下面演示)

  return 0;
}

輸出結(jié)果:
10 10
0xbfda9ccc 0xbfda9cc8
20 10
0xbfda9ccc 0xbfda9cc8

為了驗證在運行階段,a所在地址的內(nèi)容確實被*p = 20改變了,我們單步調(diào)試如下:

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;   //在這里設(shè)了斷點,先暫停查看現(xiàn)在堆棧內(nèi)容

(gdb) x/2x 0xbffff398 //從低地址查看2個字的內(nèi)容

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

(gdb) n

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

(gdb) x/2x 0xbffff398

0xbffff398: 0xbffff39c 0x00000014     //單步執(zhí)行后在查看,發(fā)現(xiàn)0xbffff39c中的值被改為0x14(20),正如上面所述

(gdb) n

20 10

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

(gdb) n

0xbffff39c 0xbffff398

19  return 0;

(gdb) 



總結(jié):編譯器會為常量分配了地址,但是在使用常量的時候,常量會被一立即數(shù)替換(保護常量,防止被破壞性修改)

在C++中對于基本類型的常量,編繹器并不為其分配存儲空間,編譯器會把它放到符號表,當取符號常量的地址等操作時,將強迫編譯器為這些常量分配存儲空間,編譯器會重新在內(nèi)存中創(chuàng)建一個它的拷貝,通過地址訪問到的就是這個拷貝而非原始的符號常量。


和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;

}

編譯運行結(jié)果:

10, 10

bfea80fc, bfea80f8

20, 20

bfea80fc, bfea80f8

可以查看二進制文件,發(fā)現(xiàn)a并沒有在鏈接的時候占用.rodata空間。

注意:可以看出a被修改了,a是在棧上分配的常量,a本身不能修改,但是可以用指針p指向a,然后修改p指向的內(nèi)容,這樣就可以修改常量a的內(nèi)容了。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多