我不明白为什么以下代码有效
typedef struct {
double x;
double y;
double z;
} abc;
static void test(abc const* b)
{
(void)memset((void *)&(b->x), 0, sizeof(double));
}
int main(int argc, char *argv[])
{
abc blah = {11, 12, 23};
printf("\n%f - %f - %f\n", blah.x, blah.y, blah.z);
test(&blah);
printf("\n%f - %f - %f\n", blah.x, blah.y, blah.z);
while (1);
}
在函数测试中,我将b设置为指向const值的指针。然而,我能够改变x的值。
答案 0 :(得分:3)
您正在使用强制转换来删除传递到const
的指针的test
- 上下文,因此在编译时允许您的操作。
blah.x
实际上是可变的,所以对此没有任何不确定。它的风格很差。
如果对象本身是const
,您的程序行为将是不确定的:
[C99: 6.7.3/5]:
如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为是未定义的。如果尝试通过使用具有非volatile限定类型的左值来引用使用volatile限定类型定义的对象,则行为是未定义的。
但是,为该对象创建const
限定句柄并不会使对象const
;它只表示你被阻止(在编译时)通过该句柄进行变异,除非你像你在这里那样砍掉了const
。
答案 1 :(得分:0)
你的(void*)
演员正在抛弃const
的{{1}} - b
; memset
能够修改该位置的内存。
这是定义明确的,因为b
最终指向不 const
的记忆。
答案 2 :(得分:0)
您明确地通过const
指针获取结构成员的地址;没有什么可以阻止您修改流程中任何地址的数据'记忆在这里;你认为结构是恒定的这一事实并不意味着你不能搞砸包含该结构的内存。
答案 3 :(得分:0)
在您的代码中,您将*b
设为常量。这不会阻止你继续前进,获取该结构的成员变量的地址,将其转换为void *
(并取消const
ness)并修改该指针所指向的值。 / p>
答案 4 :(得分:-1)
答案 5 :(得分:-6)
const
只是编译器的语法糖。你的常量存储的内存插槽没什么不同。存储正常变量的内存插槽。它只是内存,而且都是读/写内存。
将某些内容标记为const只会导致编译器禁止EXPLICIT尝试修改常量的值。例如(伪代码)
const x = 42;
x = 43; // compiler error
但是在做
const int x = 42;
*int y = &x;
*y = 43; // works
因为编译器不会检查每一个指针/内存访问,看它是否试图乱写"常量"记忆块。性能将是非常糟糕的,因为每一次内存访问都需要一堆额外的代码/扫描来检查"禁止"操作