11

我有一个包含一些指针的结构。我希望这些的价值是不可修改的。但是简单地写 const infront 并不会使结构成员不可变

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
}

有人可以指出我正确的方向。

编辑:

因此,似乎没有简单的方法可以使用函数原型来告诉属于该结构的所有内容都应该是不可修改的

4

4 回答 4

9

你可以通过定义一个 const 点类型和一个可变点类型来做到这一点,然后使用一个透明的联合:

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;

然后,您使用 point 或 const_point 类型(绝不是 mutable_point 类型)声明函数参数。

point 类型对象将透明地转换为 const_point 类型,但不是相反。这使您可以拥有更高程度的类型安全性。

请参阅此处以获取 gcc 中的示例:http: //toves.freeshell.org/xueg/

请注意,我检查的最后一个 C++ 版本不支持透明联合(不确定最新的 C++ 标准),因此您可能会遇到可移植性问题。

它还可以使代码更难阅读和维护,特别是如果你有更复杂的结构。例如:您可能有点类型,其中 x 或 y 为 const,或者您可能需要将点结构嵌入到另一个结构中,例如矩形,您可能必须根据它们的 constness 为多种类型定义多个结构。

总而言之,我不确定这是否总是值得额外的麻烦。

于 2013-10-17T23:55:40.420 回答
4

如果我正确理解您的问题,您希望将整个 struct 对象的 constness 自动传播到该 struct 成员指向的对象。即如果结构对象不是常量,则数组应该是可修改的,而如果结构对象是常量,则数组不应该是可修改的。

如果是这样,那么不幸的是,这在 C 语言中是无法实现的。

在 C++ 中,可以通过强制用户使用访问器成员函数来访问数据成员(而不是直接访问数据成员)来完成。但在 C 中它根本无法完成。

于 2012-11-01T17:09:21.550 回答
2

为了解释你需要建立什么,当你写

point str;

point *p=&str;

这里p 是指向 str 的指针,它的类型是point

当您将其声明为 const 时,这意味着 p 是一个常量指针。这并不限制结构可能包含的指针。

如果要const在结构内部应用,则必须将结构内部的指针也定义为 const

typedef struct{
   const int *  x;
   const int *  y;
}point;

再次推动我的观点,将参数声明为

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

如果它指向的结构也是 const 使用

      void get(const point * const p, int x, int y)
     //Constant Pointer to constant structure 
于 2012-11-01T16:45:12.303 回答
1

那是因为您更改了另一个指针指向的内存内容,而不是p.

p指向包含 2 个指向int. 你没有改变内存p指向,而是另一个内存区域。所以编译器对此很好。

       +----------+
p ->   |    x     |  -> wherever  
       +----------+
       |    y     |  -> another place in memory
       +----------+

constness odp是不可继承的。如果你写 了,p->a = array;那么编译器会抱怨的。这const只是一个合同,说您不会通过该指针更改内存。

于 2012-11-01T16:41:12.490 回答