C C 中取位址符 的語義和static變數

2022-04-01 05:40:16 字數 3172 閱讀 4591

c中變數的儲存方式

1.函式中的區域性變數如不作專門說明,都之auto的,即動態儲存的,auto可以省略。區域性變數也可以定義為static的,這時它在函式內值是不變的

2.靜態區域性變數如不賦初值,編譯時系統自動賦值為0,動態區域性變數如不賦初值,則它的值是個不確定的值

3。c規定,只有在定義全域性變數和區域性靜態變數時才能對陣列賦初值。 //不太懂

4.為提高執行效率,c允許將區域性變數值放在暫存器中,這種變數叫register變數,要用register說明。但只有區域性動態變數和形式引數可以作為register變數,其它不行。

52) 全域性變數的儲存方式

全域性變數在函式外部定義,編譯時分配在靜態儲存區,可以在程式中各個函式所引用。多個檔案的情況如何引用全域性變數呢?假如在乙個檔案定義全域性變數,在別的檔案引用,就要在此檔案中用extern對全域性變數說明,但如果全域性變數定義時用static的話,此全域性變數就只能在本檔案中引用了,而不能被其它檔案引用。

/** test_memory.c

** created on: 2009-10-3

* author: lengyuex

*/#include

#include

#include

static int d=9;

int z = 9;

int *p=&z;

int a;

static int b =10;

static int c;

void swap(int* x,int* y)

int main()

;int i;

for (i=0;i printf ("the f[i]=%d\n",f[i]);

int t[5];

for (i=0;i t[i]=i+2;

for (i=0;i printf ("the t[i]=%d\n",t[i]);

int x=4,y=5;

printf ("before swap() a=%d,b=%d,c=%d,z=%d,d=%d\n",a,b,c,z,d);

printf ("the no init e=%d\n",e);

swap(&x,&y);

printf ("after swap() d=%d\n",d);

printf("x=%d,y=%d,z=%d,w=%d\n",x,y,z,b);

return 0;

}輸出:

[lengyuex@tux algorithm]$ ./a.out

no define in main ,the d=9

the f[i]=1

the f[i]=2

the f[i]=3

the f[i]=4

the f[i]=5

the t[i]=2

the t[i]=3

the t[i]=4

the t[i]=5

the t[i]=6

before swap() a=0,b=10,c=0,z=9,d=0

the no init e=11472064

in swap() the d=8

after swap() d=0

x=5,y=4,z=9,w=10

變數儲存在什麼地方:

分配效率:棧是機器系統提供的資料結構,電腦會在底層對棧提供支援:分配專門的暫存器存放棧的位址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是c/c 函式庫提供的,他的機制是很複雜的,例如為了分配一塊記憶體,庫函式會按照一定的演算法(具體的演算法能夠參考資料結構/作業系統)在堆記憶體中搜尋可用的足夠大小的空間,假如沒有足夠大小的空間(可能是由於記憶體碎片太多),就有可能呼叫系統功能去增加程式資料段的記憶體空間,這樣就有機會分到足夠大小的記憶體,然後進行返回。顯然,堆的效率比棧要低得多。

c/c++中的指標其實就是乙個變數,和其他型別的變數是乙個樣子的,它是乙個占用四位元組的變數(32位機上),它與其他變數的不同之處就在於它的變數值是乙個記憶體位址,指向記憶體的另外乙個地方。reference我的理解就是乙個別名,它和linux作業系統上的alias是乙個樣子的。再者,乙個 pointer變數可以指向null,表示它不指向任何變數位址,但是reference必須在宣告的時候就得和乙個已經存在的變數相繫結,而且這種繫結不可改變。

在c語言中,&符號大家一定很熟悉吧。

它除了可以作為按位運算「與」之外還有更常用的功能——取變數位址。

我們首先看下面乙個簡單的例子:

#include

int main(void)

上面**中,指標p指向變數a的位址。在c/c++中,每個變數都有其相應的位址,通過在變數識別符號前加&符號即可獲得變數的位址。

那麼我們這麼寫可以嗎?int *p = &0x01000;

這顯然不行。因為對於乙個數值常量,它是沒有位址的。而變數之所以有位址就是因為要有乙個儲存單元對變數進行標識(當然,變數也可以直接對映到某個暫存器)。

我們再看下面的**:

#include "stdio.h"

int main(void)

上面**又是怎麼回事呢?

先前已經調查過變數a的位址——0x0012ff60,那麼這裡的指標p實際上也是指向變數a的位址。

首先,將0x0012ff60作為int*,這時它與&a是等價的。

然後*(int*)0x0012ff60表示取變數a的內容。

最後,&*(int*)0x0012ff60表示再脫去*(int*)0x0012ff60的解引用,相當於又變為(int*)&a。

因此,這裡的&與第乙個例子中的&是不同的語義。這裡的&不是取位址,因為乙個*(int*)0x0012ff60不是變數,它是沒有位址的。每乙個變數識別符號在編譯期間,編譯器會為它們建立乙個符號表,其中存放著變數識別符號相應的各種屬性,如型別、位址標識等。位址標識在連線後即可確定邏輯位址值。簡而言之,&作為取位址操作,當且僅當&後面跟著的是變數或函式識別符號。所以這裡的&表示脫去解引用。

由此我們可以得出:&作為取位址操作時,其行為結果是在編譯時就被確定的;而*,解引用操作(或取內容)操作,其行為結果只能在執行時才可被確定。

再看下面的例子,加深印象:

#include "stdio.h"

int main(void)

在c++中,&還可以表示引用,這個就不多說了。

#include "iostream"

using namespace std;

int main(void)

C C 中取位址符 的語義

在c語言中,符號大家一定很熟悉吧。它除了可以作為按位運算 與 之外還有更常用的功能 取變數位址。我們首先看下面乙個簡單的例子 include int main void 上面 中,指標p指向變數a的位址。在c c 中,每個變數都有其相應的位址,通過在變數識別符號前加 符號即可獲得變數的位址。那麼我們...

C 中的取位址符

這個符號特別容易混淆,因為在c 中,有兩種不同用法 獲得變數位址 引用傳遞 第乙個例子,int main 0x7ffd05129510 hello finished in 0.2s 例子中,變數p使用 宣告為指標,將變數s的位址通過 符號賦值給p.int main hello hello new h...

取位址符的用法總結

一種是按位與 1 2 0 一種是取位址 int p a 一種是宣告引用,相當於定義變數別名 int a 3 int b a b是 a的引用,a,b是同乙個變數 b 4 a也變化為 4int c 2 b c 是賦值給b或 a,而不是把b作為 c的引用,引用一旦被宣告,引用物件不可更改 引用的實質是指標...