簡體   English   中英

C -- 通過別名非常量指針修改常量

[英]C -- Modify const through aliased non-const pointer

它是在標准C允許修改的功能int給出const int *使用別名int * 換句話說,以下代碼是否保證在標准 C 中始終返回 42 和 1?

#include <stdio.h>

void foo(const int *a, int *b)
{
    printf("%d\n", *a);
    *b = 1;
    printf("%d\n", *a);
}

int main(void)
{
    int a = 42;
    foo(&a, &a);
    return 0;
}

在您的示例代碼中,您有一個整數。 你用一個 const 指針指向它,一個非常量指針指向它。 當然,通過非常量指針修改整數是合法且定義明確的。

由於兩個指針都是指向整數的指針,並且 const 指針不需要指向 const 對象,因此編譯器應該期望從 const 指針讀取的值可能已更改,並且需要重新加載該值。

請注意,如果您使用了restrict關鍵字,則情況並非如此,因為它指定指針參數不為任何其他指針參數設置別名,因此編譯器可以優化重新加載。

是的,是的。 您的程序已定義。

使用指向 const int 的指針指向非常量 int 變量這一事實不會使該變量成為 const,並且仍可能通過指向 int 的指針或使用原始變量標簽進行修改。

是的,你可以這樣做(如果你知道你可以逃脫它)。

您可能無法擺脫它的一個原因是,如果您要寫入的目標內存位於只讀保護區(例如常量數據)中,那么您將遇到訪問沖突。 例如,任何在編譯時最終出現在可執行文件的只讀數據部分中的常量。 大多數平台支持保護它在運行時不被寫入。

基本不做。

您的示例還存在其他問題,可能無法使其成為最佳演示。 例如需要在第二個 printf 中重新加載 *a 編譯器可能會優化它! (它知道 'a' 沒有改變,它知道 'a' 指向一個常量,因此,它不需要通過為第二個 '*a' 表達式執行內存加載來重新加載內存,它可以重用它可能的值從第一次加載'*a'開始在寄存器中。 現在,如果您在兩者之間添加內存屏障,那么您的示例就有可能更好地工作。

https://en.wikipedia.org/wiki/Memory_barrier GCC ? asm volatile ("" :: : "memory"); // 可能在第二個 printf 之前工作

但是對於您提出的實際問題的負責人,是的,如果您知道自己正在對其他類似的事情做什么,那么您就可以做到。

是的,它保證總是打印 42 和 1。

const int *a表示指向的值是指針a的常量。

嘗試從函數中的a ( *a = 10; ) 取消引用,您將收到錯誤消息。

然而,指針a不是常數。 例如,您可以執行a = b

b可以指向相同的地址作為a和/或修改的值,當你在你的例子一樣。 您是否將b指針的值聲明為常量( const int *b ),您將收到錯誤消息。

我試着像這樣記住:

const int *a - a 指向一個 int 類型的對象,它不允許修改(任何其他指向該對象的指針都可以做它想做的事,取決於它的聲明/定義)。

暫無
暫無

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

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