问题
I have a struct which contains some pointers. I want the value of these to be unmodifiable. But simply writing const infront doesn't make the structs members unmutable
typedef struct{
int *x;
int *y;
}point;
void get(const point *p,int x, int y){
p->x[0]=x;//<- this should not be allowed
p->y[0]=y;//<- this should not be allowed
}
Can someone point me in the right direction.
EDIT:
So it would seem that there is no simple way of using the function prototype to tell that everything belonging to the struct should be unmodifiable
回答1:
To explain what you need to establish, when you write
point str;
point *p=&str;
Here p is a pointer to str which is of type point
When you declare it as const, it means that p is a constant pointer. This does not restrict the pointers that the structure may contain.
If you want the const
ness to apply inside the structure, you have to define the pointers inside the structure also as const
typedef struct{
const int * x;
const int * y;
}point;
Again to push home my point declare the parameter as
void get(point * const p,int x, int y)
//Constant Pointer ( *to prevent p from pointing to anything else*)
// AND
//Make the pointers inside point structure constant
//( *to prevent the int pointers x & y from pointing to anything else*)
If the structure it is pointing to is also const use
void get(const point * const p, int x, int y)
//Constant Pointer to constant structure
回答2:
You can do it without typecasting by defining a const point type and a mutable point type, then use a transparent union:
typedef struct{
const int * x;
const int * y;
} const_point;
typedef struct{
int * x;
int * y;
} mutable_point;
typedef union __attribute__((__transparent_union__)) {
const_point cpoint;
mutable_point point;
} point;
Then, you declare your function parameters using either the point or const_point type (never the mutable_point type).
point type object will transparently cast to a const_point type, but not the reverse. This allows you to have a greater degree of type safety.
See here for an example in gcc: http://toves.freeshell.org/xueg/
Note that transparent union was not supported in the last version of C++ I checked (not sure about the latest C++ standard) so you can expect portability issues.
It can also make the code harder to read, and maintain, especially if you have more complex struct. e.g.: you could have point type where either x or y is const, or you may need to embed your point structure into a another struct, e.g. rectangle, for which you might have to define multiple struct for multiple type depending on their constness.
All in all, I'm not sure it's always worth the extra trouble.
回答3:
If I understand your question correctly, you would like to get automatic propagation of constness of the entire struct object to the objects pointed by that struct members. I.e. if the struct object is not const, the arrays should be modifiable, while if the if the struct object is const, the arrays should not be modifiable.
If so, then, unfortunately, it is not achievable in C language.
In C++ it can be done by forcing the user to use accessor member function to access the data members (instead of accessing data members directly). But in C it simply can't be done.
回答4:
That's because you change the memory content pointed to by another pointer than p
.
p
points on a structure containing 2 pointers to int
. You don't change the memory p
is pointing to, but another memory area. So the compiler is fine with that.
+----------+
p -> | x | -> wherever
+----------+
| y | -> another place in memory
+----------+
The const
ness od p
is not inheritable. If you had written p->a = array;
then the compiler would have complained.
The const
is only a contract saying that you won't change the memory through that pointer.
来源:https://stackoverflow.com/questions/13181546/const-correctness-for-structs-with-pointers