2015-06-20 96 views
1

請考慮下面的程序:空指針的函數參數

#include <iostream> 
void f(void* a) 
{ 
    std::cout<<"(void*)fun is called\n"; 
    std::cout<<*(int*)a<<'\n'; 
} 
int main() 
{ 
    int a=9; 
    void* b=(int*)&a; 
    f(b); 
    return 0; 
} 

如果我改變函數調用語句是這樣的:

f(&b);

它仍然在運行時編譯罰款&崩潰。爲什麼?是什麼原因?我不應該得到編譯時錯誤?因爲調用函數的正確方法是f(b)。對?此外,爲什麼允許將NULL傳遞給參數類型爲(void *)的函數?

請糾正我如果我錯過了某些東西或錯誤地理解了某些東西。

+2

指針的指針仍然是一個指針,所以它被接受爲void *。 – Ely

+0

你可能打算通過'a'的地址來達到同樣的效果:'f(&a);' –

+5

@meet雖然EdHeals的評論並不完美,但基本上他是對的,如果你不明白這是什麼,你不需要任何指針 – deviantfan

回答

5

它仍然正常編譯&在運行時崩潰。爲什麼?是什麼原因?

因爲void*是一種去除所有類型安全和類型檢查的技術。

我不應該得到編譯時錯誤嗎?

通過使用void*而不是正確的指針類型int*,您明確告訴編譯器不告訴你,如果你使用的是錯誤的類型或處於不確定的方式。

因爲調用函數的正確方法是f(b)。對?

這就是你的函數聲明內容不同意。

std::cout<<"(void*)fun is called\n"; 
    std::cout<<*(int*)a<<'\n'; 

內容上面暗示的指針,int應傳遞:

void f(void* a) 

聲明意味着一些指針應該過去了,並沒有其他限制時。

2

void*可以捕捉任何類型的指針,沒有例外void**

+0

爲什麼它在運行時崩潰了? – Destructor

+0

@meet,你把'b'的地址解釋爲一個'int *',但是'b'本身就是一個指針,而不是'int'。 – chris

1

首先

你可以有一個void*void**。你的代碼是很多例子中的一個,顯示指針的危險程度。

你應該進行類型轉換使用:

void* b = static_cast<int*>(&a);

而不是C風格轉換使用的是:

void*b = (int*)&a; 
1

好的。

按要求。

不要使用void指針,除非它無法想到其他任何方式。

然後去睡覺,再想一想。

無效指針使程序員可以忘記類型。這意味着編譯可以放棄簡單的檢查。這也意味着程序員已經失去了情節。

如果您願意的話,請給我一個讚賞。

使用類型有一個好處,編譯器可以檢查你的東西。例如。事情是如何相關的。如何對待這個對象。

但是使用一個void指針,你是非常靠自己的。祝你好運

1

因爲f(&b)電話f和傳遞的b的地址作爲參數,然後將其鑄造成一個void*你不會得到一個編譯時錯誤。你會得到一個運行時錯誤,因爲這樣你就試圖將一個指針指向一個整數作爲整數。 但是,正如其他人所說,這樣做很糟糕。

1

如果我改變這樣的函數調用語句: f(& b); 它仍然在運行時編譯罰款&崩潰。爲什麼?

您的功能f(void*)將接受指向任何類型的指針,而無需投訴。任何指針悄悄地轉換爲空指針。指向指針的指針仍然是一個指針。所以你的第二個例子確實編譯得很好。然後它崩潰。也許。

在第一種情況下,您從一個指針轉換爲一個指向無效的指針,返回指向int的指針。通過void*(以及通過char*)的往返轉換必須正常工作。在第二種情況下,您從void**轉換爲void*轉換爲int*。現在你調用未定義的行爲。什麼都可以。在我的電腦上,我的編譯器,你的代碼運行得很好。它打印垃圾。我很確定你的代碼不會擦除我的硬盤,但它可以。任何事情都會發生未定義的行爲。不要調用未定義的行爲。

支持void*的原因是歷史性的。有很多舊的C和C++代碼使用void指針。 只有編寫使用void指針的新C++代碼的原因是,如果您需要與使用void指針的那些舊函數之一進行交互。

0

我發現自己在這裏,因爲我正在做一個家庭作業,要求相同的功能。結合每條評論後,這就是我想出的。編譯器不會在運行時崩潰。

` 
// A function that accepts a void pointer 
void f(void* a) 
{ 
    std::cout<<"(void*)fun is called\n"; 
    std::cout<< "value for a: " << *(int*)a << '\n'; 
} 


int main() { 
    int a = 9; 
    void* c = static_cast<int*>(&a); 

    int b = 3; 
    f(&b); 
    f(c); 
} 
`