2017-06-14 97 views
2

我必須要改變一個const結構實例的const成員在C.是否有可能在C中更改一個const struct成員?

我已經知道它是可以改變一個const類型基本如下:

const int a = 2; 
*(int*)&a = 3; 

我也可以改變一個const成員一個結構實例如下:

typedef struct ST { 
    const int a; 
    const int b; 
}ST; 
ST st = {.a = 1,.b =2}; 

int main() { 
    *(int *)(&((*(ST*)(&st)).a)) = 5; //works fine , no problem 
} 

但是我沒有成功,試圖改變結構實例的const成員,如果實例是不變的:

typedef struct ST { 
    const int a; 
    const int b; 
}ST; 

const ST st = {.a = 2,.b=3}; //const instance 

int main() { 
    *(int *)(&((*(ST*)(&st)).a)) = 5; //does not work(Seg fault)!! 
} 

那麼,有可能在最後一種情況下更改「a」成員值嗎? 如果不是,爲什麼?

+5

所有這些都是未定義的行爲 –

+0

我想修改一個const成員。這是一個矛盾。你的設計需要改變。 –

+0

另外,請打開所有警告。在第一種情況下,你的編譯器會抱怨將'const int *'強制轉換爲'int *'。 –

回答

10

我已經知道它是可以改變一個const類型基本如下:

const int a = 2; 
*(int*)&a = 3; 

你的編譯器可以讓你做到這一點並不能使法律的事實。此代碼調用未定義的行爲,因此如果您在不同的平臺上運行該程序或使用其他編譯器,則相同的程序可能會失敗或崩潰。

*(int *)(&((*(ST*)(&st)).a)) = 5; //works fine , no problem 

此代碼有同樣的問題:它會調用未定義的行爲。

您嘗試的最後一段代碼也有(您猜對了!)未定義的行爲。然而,這一次,程序崩潰而不是運行完成。

0

C編譯器通常將常量放在只讀內存段中,通常稱爲.TEXT或.CODE。此段(內存塊)受操作系統的保護,或者對於小型嵌入式CPU和SoC常量通常與代碼一起放置在ROM /閃存中。不建議您嘗試執行的操作,因爲它會影響使用常量的所有模塊。

如果您對內存分段感興趣並感受編譯器和鏈接器如何管理內存,請嘗試更改鏈接選項以生成映射文件。

但是,事實上,只要常量位於可寫入的數據段中,您就可以輕鬆更改常量結構中的const成員。你可以試試這個:

int someFunc() 
{ 
    const ST CONST_ONSTACK = { .a = 10, .b = 20 }; // the constant is on the stack... 
    *(int*)&(CONST_ONSTACK.a) = 3} 
    return CONST_ONSTACK.a; 
} 

如果你的編譯器是好的,你應該得到一個警告。

相關問題