#include<stdio.h>
int main() {
int a[10] = {1, 2, 3, 4};
const int *pa = a;
*(pa 2) = 4; // error
char b[4] = "abc";
const char *pb = b;
*(pb 2) = 'c'; // error
int c = 10;
const int *pc = &c;
*(pc 2) = 4; // error
}
From my understanding, the const int/char *
only restricts that we cannot modify the value it points to. However, it seems that modify *(pa 2)
will also result in an error. Why is this happening?
CodePudding user response:
Because is pa 2
has the same type as pa
. Either you want to prevent the array from being modified, or you don't, so it makes sense for the result to have the same type as the original pointer.
CodePudding user response:
First, note that const
is largely an assistance mechanism that aids programmers in avoiding errors, rather than an enforcement mechanisms that always prevents them. Data defined with const
may be put into read-only memory (the C implementation is allowed to do so, and it is also allowed not to do so), and then attempting to modify that memory (without working around it by requesting the operating system to change the memory protection) will yield a segment fault. Otherwise, const
is largely advisory, not enforced.
The specific rule that says a compiler must complain about *(pa 2) = 4;
is in C 2018 6.5.16 2, which discuss the assignment operators. This rule is based on the types of the expressions involved, not on what objects in memory they actually point to. Since pa
is a pointer to const int
, pa 2
is also a pointer to const int
(C 2018 6.5.6 8: “When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand…”). Then *(pa 2)
is an lvalue designating the object that pa 2
points to, and the type of the lvalue is const int
(C 2018 6.5.3.2 4: “… If the operand has type "pointer to type", the result has type "type"…”).
So *(pa 2) = 4;
is an attempt to assign to an lvalue of type const int
. C 2018 6.5.16 2 says “An assignment operator shall have a modifiable lvalue as its left operand.” A const int
is not a modifiable type, so it is not a modifiable lvalue. This paragraph is in a Constraints section, which means the compiler is require to issue a diagnostic message for the violation of it.