簡體   English   中英

GCC:在獲取地址時取消引用“ void *”指針

[英]GCC: dereferencing ‘void *’ pointer while taking address

我注意到GCC觸發器:

warning: dereferencing ‘void *’ pointer

在采用已取消引用的void表達式的地址時,例如:

int main()
{
    void *p = "abcdefgh";

    printf("%p\n", p);
    printf("%p\n", &*p);

    return 0;
}

但是,根據C標准,表達式p等於&*p

§6.5.3.2地址和間接運算符

一元&運算符返回其操作數的地址。 如果操作數的類型為“類型”,則結果的類型為“類型的指針”。 如果操作數是一元*運算符的結果,則不會對該運算符和&運算符求值,並且結果都好像都被省略了,除了運算符上的約束仍然適用並且結果不是左值。

同樣重要的是要知道Clang不會觸發此警告。

免責聲明

為了獲得更好的解釋,請考慮以下事項:

int main()
{
    int *p = NULL;

    printf("%p\n", (void *) p);
    printf("%p\n", (void *) &*p);

    return 0;
}

該代碼可與Clang和GCC一起編譯並完美運行。 C標准對void指針很清楚,您可以取消引用它們(從而獲得一個void值),但不能使用表達式的結果。

我假設這里的問題是“為什么?/有什么用?”。 在這種情況下,這實際上是一些標准的措辭/針對編譯器開發人員的靈活性。

嚴格來說*(void*)總是不好的,編譯器可以警告您。 在實踐中,正如您正確指出的那樣,在評估指針所指向的內容時,指針實際上從未真正被取消引用,因此,天真的編譯器實現將以這種方式查看並毫無問題地進行掩飾這並說“指針:它們是數字對嗎?這是0xFFF ....”。

實際上,有時並非如此。 有時候編譯器變得很聰明。 沒有想到好的例子,但這不是重點。

關於“從未被評估”,我認為可能需要注意以下幾點:

賦予編譯器自由執行其所需功能的原因,部分原因是為了簡化編譯過程本身,而不僅僅是輸出更好的實現。 您指向的下一個編譯器可能會拒絕。 只是因為它更容易,而且沒有必要。

其次,這並不是警告的重點。 如果我在代碼審查中看到了這一點:

int i = 3;
if (3-i) {
    ((int*)(NULL)) += 4;
}

我的反應不會是:“哦,還好,沒有評估。” 但是“哇!”。 這也是編譯器所做的。 它告訴您它認為您可能已經做了一些可能需要重新考慮的事情,在這種情況下,將const char *稱為void * 我同意gcc。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM