2013-07-22 28 views
0

有人可以向我解釋這種行爲嗎?將地址轉換爲長變量結果的值?

static short nDoSomething(const char* pcMsg, ...) 
{ 
    va_list pvArgument; 
    long lTest; 
    void* pvTest = NULL; 

    va_start(pvArgument, pcMsg); 

    pvTest = va_arg(pvArgument, void*); 
    lTest = (long) pvTest; 

    va_end(pvArgument); 
    return 0; 
} 

如果我調用此函數的主要是這樣的:

int main(int argc, char* argv[]) 
{ 
    char acTest1[20]; 
    nDoSomething("TestMessage", 1234567L, acTest1); 


    return 0; 
} 

我認爲pvTest的地址將是Ltest來,但實際上它包含1234567 ...

這怎麼可能?

+1

當你說地址_of_'pvTest'時,你的意思是:地址'pvTest'指向,對吧?你很困惑,爲什麼_that_是'1234567',對嗎? – jogojapan

+0

是的,這是正確的! – skylla

+0

要得到'pvTest'的地址,你必須得到它的地址:'(long)&pvText'。 –

回答

1

你的代碼中包含未定義的行爲;該標準要求 使用va_arg提取的類型對應於類型 通過(模cv-qualifiers,也許):您通過了long, 讀取void*,因此編譯器所做的任何事情都是正確的。

實際上,大多數編譯器生成的代碼不包含 類型的檢查。如果在您的機器上,longvoid*尺寸相同(並且機器具有線性尋址),則您可能會以long結束所傳遞的任何內容。如果 兩者的大小不同,但機器是小端,並且您的 傳遞足夠小的值,則最終可能會得到相同的值 。但是這並不能保證。

1

你只是在這裏幸運。

va_start(pvArgument, pcMsg); 

準備va_arg(pvArgument,T)以提取下一個變量 參數與它是T類型的推定以下pcMsg

pcMsg之後的下一個參數實際上是long int 1234567;但是 您錯誤地將其解壓爲void *,然後將其轉換爲long轉換爲 lTest。你很幸運,你的系統上的void *是 ,與long的尺寸相同。

(或者,也許我的意思是奇怪不吉利