سؤال

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

هل كانت مفيدة؟

المحلول

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 

نصائح أخرى

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.

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.

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 constness 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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top