天天看點

C語言中的&位址操作符(轉)

#include <stdio.h>
int find(int *a);
main()
{
    int b = 1;
    int wait, test;
    test = find(&b);
    printf("記憶體位址為:%d",&test);
    scanf("%d", &wait);
}
int find(int *a)
{
    return *a;
}      

int b = 1; int test = find(&b); 這樣調用時,實際上是進行了:int* a = &b,建立了一個新的指向b的整型指針a作為find函數範圍内的局部變量。

示例二

函數聲明:int find(int& a); 函數調用:int b = 1; int n = find(b);

這樣調用時,實際上是進行了:int& a = b,給變量b起了個别名a,也就是說a和b實際上代表的是同一個變量,調用期間沒有建立任何新的變量。

示例三

函數聲明:int find(int a); 函數調用:int b = 1; int n = find(b);

這樣調用時,實際上是進行了:int a = b,也就是普通的變量指派操作,調用期間建立了在find函數範圍内的局部變量a,它的值與b相同。

C中*、&用法介紹

&在用于計算時就是取變量位址,如int* a = &b,就是将整型變量b的位址取出,指派給整型指針a,a中的内容就是b的位址,是以a指向b。

*在用于計算時,就是取指針所指向的位址中的值,如int b = *a,就是将整型指針a指向的位址中存放的内容指派給整型變量b。

C語言中,&符号大家一定很熟悉吧,它除了可以作為按位運算“與”之外還有更常用的功能——取變量位址。

#include <stdio.h>
main()
{
    int a = 0;
    int wait;
    int *p = &a;
    printf("The value is: %d\n", *p);
    scanf("%d", &wait);
}      

上面代碼中,指針p指向變量a的位址。在C/C++中,每個變量都有其相應的位址,通過在變量辨別符前加&符号即可獲得變量的位址。

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

這顯然不行。因為對于一個數值常量,它是沒有位址的。而變量之是以有位址就是因為要有一個存儲單元對變量進行辨別(當然,變量也可以直接映射到某個寄存器)。

我們再看下面的代碼:

#include "stdio.h"
int main(void)  
{  
    int a = 0; // &a = 0x0012ff60  
    int *p = &*(int*)0x0012ff60;  
    printf("The value is: %d\n", *p);  
    return 0;  
}      

上面代碼又是怎麼回事呢?

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

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

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

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

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

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

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

#include "stdio.h"
int main(void) 
{ 
    int a = 0;
    int *p = &*&*&a;
    printf("The value is: %d\n", *p);
    return 0; 
}      

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

#include "iostream" 
using namespace std;
int main(void) 
{ 
    int a = 0;
    int &r = a;
    cout << "The value is: " << r << endl;
    return 0; 
}      

繼續閱讀