2017-06-14 68 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; 
} 

如果你的编译器是好的,你应该得到一个警告。

相关问题