memcpy with destination pointer to const data

此生再无相见时 提交于 2020-01-02 04:34:07

问题


I always thought that an statement like const int *a means a is an int pointer to const data and as such one should not be able to modify the value it points to. Indeed if you do const int a [] = {1,2,3} and then issue a[0] = 10 you'll get compiler errors.

To my surprise, however, the following compiles without any warning and runs just fine.

#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;
} 

Why is this allowed? Is this due to the cast? When I do memcpy(&a[0], (const void*)&b[0], 3*sizeof(int)); compiler promptly generates the following warning:

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 *’

回答1:


Casts usually suppress warnings. There is a gcc option, -Wcast-qual that will warn you about casts that are losing a const or volatile qualifier.

The program ran successfully because the memory used to store the array wasn't actually readonly, because they were allocated on the stack. This is an implementation detail and technically your code could have crashed if the implementation was really strict.

Declare a and b as globals and there's a greater chance it will crash (still not a guarantee)




回答2:


You told the compiler to disregard the initial declaration when you performed the cast. It listened. That doesn't mean that your program is correct however. Modifying what was originally declared to be const results in undefined behavior (for example, the compiler is free to store that data in read only memory).

C doesn't hold your hand. If you chose to do something dangerous then it will let you.




回答3:


Casting to void* removes the association with an int - by throwing away the type, you throw away the type decorators, such as const

Edit

As from discussion below, I want to make clear, that the important part is not to what you cast (void* in the OQ), but the fact that you cast - this implies throwing away your original type and its decorators.



来源:https://stackoverflow.com/questions/12309600/memcpy-with-destination-pointer-to-const-data

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!