變量名和變量地址
?
研一時,很偶然的翻開譚浩強老先生的《C程序設計》(是師姐的書,俺的老早就賣了,估計當時覺得這本書寫得不夠好),很偶然的看到關于變量名的一段話:“變量名實際上是一個符號地址,在對程序編譯連接時由系統給每一個變量名分配一個內存地址。在程序中從變量中取值,實際上是通過變量名找到相應的內存地址,從其存儲單元中讀取數據。”
當時很震驚上課的時候居然沒有發現這句蠻有深意的話語,可是研一的時候還是沒有完全明白,只是知道有這么幾個東西:變量名、內存地址、變量值。后來看到指針的地方,說到了“符號表”的這個東東,就更頭大了。符號表到底是個什么樣子?那個變量名到底放在內存的什么地方?
最近在寫驅動,面對的是一個芯片手冊,幾百個寄存器。現在來看,才發現其實還是蠻簡單的。
?
芯片手冊大概是這么寫的:
地址 | 名稱 | 值 |
0x00 | CHIP_ID | 0x03 |
0x01 | CHIP_VERSION | 0xA2 |
0x02 | …… | …… |
0x03 | ? | ? |
?
那么,“符號表”其實就是“名稱”的那一列,把所有的名稱放在一起就是一個符號表了嘛。
“通過變量名找到內存地址”也很簡單,比如說定義一個宏:#define CHIP_ID_ADDR?????? 0x00就可以了。
read函數可以這么寫:
xxx_read_val(addr, retval)
{
?????? retval = *addr;
}
調用的時候也很容易:
xxx_read_val(CHIP_ID_ADDR,&val);
這也可以算是所謂的“通過變量名找到內存地址,,從其存儲單元中讀取數據了。”
那么,比如說定義一個char a = ‘P’;
編譯時會為a分配一個地址,是把a和P填在表上,就是:
?
地址 | 名稱 | 值 |
0x00 | CHIP_ID | 0x03 |
0x01 | CHIP_VERSION | 0xA2 |
0x02 | a | 0x50 |
0x03 | …… | …… |
?
?
?
?
/*在對程序編譯連接時由編譯系統給每一個變量名分配對應的內存地
址,該地址分配后不可改變,直到該空間被釋放*/
#include <iostream.h>
void main()
{
int val1 = 10, val2 = 20;
int temp;
cout << "Before swap, val1 =" << val1 << " ?" <<?
"val2 =" << val2 << endl;
cout << "Before swap, val1 =" << &val1 << " ?" <<?
"val2 =" << &val2 << endl;
temp = &val1; ? //錯誤:改變了變量的內存地址
&val1 = &val2;
&val2 = temp;
cout << "After swap, val1 =" << val1 << " ?" <<?
"val2 =" << val2 <<endl;
cout << "After swap, val1 =" << &val1 << " ?" <<?
"val2 =" << &val2 <<endl;
}
?
報錯error C2106: '=' : left operand must be l-value
解釋:賦值號(‘=’)左邊的操作數必須是一個左值。通俗的說:左值就是可以改變值的變量。
發生這個錯誤的原因是你把常量(或不可改變值的變量)放到了賦值號的左邊。此處就是因為變量val1,val2的地址是不可改變的量,才導致出錯。
?