我一直认为像const int *a
这样的语句意味着a
是指向int
数据的const
指针,因此我们不应该修改它指向的值至。实际上,如果您执行const int a [] = {1,2,3}
然后发出a[0] = 10
,则会出现编译错误。
然而,令我惊讶的是,以下编译没有任何警告,运行得很好。
#include <stdio.h>
#include <string.h>
int main (){
const int a [] = {1, 1, 1};
const int b [] = {2, 2, 2};
memcpy((void*) &a[0], (const void*)&b[0], 3*sizeof(int));
int i;
for (i=0; i<3; i++) printf("%d\n",a[i]);
return 0;
}
为什么允许这样做?这是由于演员吗?当我memcpy(&a[0], (const void*)&b[0], 3*sizeof(int));
时,编译器会立即生成以下警告:
cpy.c: In function ‘main’:
cpy.c:9:3: warning: passing argument 1 of ‘memcpy’ discards ‘const’ qualifier from pointer target type [enabled by default]
/usr/include/string.h:44:14: note: expected ‘void * __restrict__’ but argument is of type ‘const int *’
答案 0 :(得分:5)
您告诉编译器在执行强制转换时忽略初始声明。它听了。但这并不意味着您的程序是正确的。修改最初声明为const
的内容会导致未定义的行为(例如,编译器可以将该数据存储在只读内存中)。
C不握你的手。如果你选择做一些危险的事情,它会让你。
答案 1 :(得分:4)
转换为void*
会删除与int
的关联 - 通过丢弃该类型,您会丢弃类型装饰器,例如const
修改强>
从下面的讨论中,我想明确一点,重要的部分不是你在void*
),而是那个< / strong>你施放 - 这意味着扔掉原来的类型及其装饰者。
答案 2 :(得分:2)
强制转换通常会禁止警告。有一个gcc选项,-Wcast-qual
会警告您丢失const
或volatile
限定符的演员。
程序成功运行,因为用于存储数组的内存实际上并不是只读的,因为它们是在堆栈上分配的。这是一个实现细节,从技术上讲,如果实现非常严格,您的代码可能会崩溃。
将a
和b
声明为全局变量,崩溃的可能性更大(仍然不能保证)