5

我一直认为像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 *’
4

3 回答 3

5

您告诉编译器在执行强制转换时忽略初始声明。它听了。但是,这并不意味着您的程序是正确的。修改最初声明的内容会const导致未定义的行为(例如,编译器可以自由地将该数据存储在只读存储器中)。

C没有牵你的手。如果您选择做一些危险的事情,那么它会让您。

于 2012-09-06T23:03:16.113 回答
4

强制转换为void*删除与int- 通过丢弃类型的关联,您丢弃了类型装饰器,例如const

编辑

从下面的讨论中,我想明确指出,重要的部分不是投射的内容(void*在 OQ 中),而是你投射的事实-这意味着丢弃你的原始类型及其装饰器。

于 2012-09-06T23:00:29.873 回答
3

强制转换通常会抑制警告。有一个 gcc 选项,-Wcast-qual它会警告您丢失constvolatile限定符的演员表。

程序成功运行是因为用于存储数组的内存实际上不是只读的,因为它们是在堆栈上分配的。这是一个实现细节,从技术上讲,如果实现非常严格,您的代码可能会崩溃。

声明ab作为全局变量,它崩溃的可能性更大(仍然不能保证)

于 2012-09-06T23:04:38.917 回答