如何使用const成员操作结构数组

时间:2016-05-04 19:15:27

标签: c struct const

我试图了解' const'在C工作。 我想创建的是polygon struct,其成员不能被变异。

我首先创建了以下结构

struct vector2{
    float x;
    float y;
};

struct polygon2{
    const size_t count;
    struct vector2* const points;
};

要创建多边形,我创建了以下函数:

struct polygon2* polygon2_create(size_t count)
{
    struct vector2* points = calloc(count, sizeof *points);
    struct polygon2 temp = {.count = count,
                            .points = points};
    struct polygon2* actual = malloc(sizeof *actual);
    memcpy(actual, &temp, sizeof(*actual));

    return actual;
}

I believe this function doesn't cause undefined behavior.

这样我可以做像

这样的事情
struct polygon2* poly = polygon2_create(30);
poly->points[3] = (struct vector2){7.1, 5.3};

但我无法做到

poly->points = NULL;

也不

poly->count = 3;

哪个好。我确信我不会意外更改struct polygon的内容。

但我也想让vector2成员成为const。 如果我将vector2更改为:

struct vector2{
    const float x;
    const float y;
};

我再也无法做到这一点:

poly->points[3] = (struct vector2){7.1, 5.3};

我想知道原因。我期望将vector2&#39的成员变成const我将无法做到这一点

poly->points[3].x = 3

但我仍然能够做到这一点

poly->points = otherpoint;

有人可以解释我错过了什么吗?我怎样才能实现以下目标:

  • 创建一个"不可变的" vector2 struct
  • 创建一个polygon struct,其pointscount成员无法更改,但points指向的内容可以“#{}}' swaped&#39 ;

1 个答案:

答案 0 :(得分:2)

const对类型的限定意味着该类型的左值表达式不可修改。特别是,递归地,const类型或具有至少一个const成员的复合类型的左值不能是赋值运算符的左侧,并且指向这些对象的指针不能是{{1 }} d。

此外,合格的,包括free() - 限定类型的类型与其不合格的对应类型和基础非限定类型的不同限定版本不同。这会影响具有合格成员的复合类型的兼容性。

另一方面,不要将const误认为该值实际上是常数的承诺。情况可能是同一个对象可以由多个左值指定,一些const和其他非const。在这种情况下,可以通过指定它的任何非const左值来修改对象,即使通过指定它的const左值,这些修改也是可见的。

关于你问题的具体细节:

  • 我同意您的函数const有效且行为明确。特别是,结构的polygon2_create()成员可以在初始化程序中初始化,而诸如const之类的函数可以修改存储器,在该存储器中可以存储可以通过memcpy()左值引用的对象。但是,您的编译器可能会警告const
  • 更一般地说,您描述的初始化和赋值行为和约束是正确的。
  • 至于memcpy(),如果poly->points[3] = (struct vector2){7.1, 5.3};的成员是struct vector2,那么如何理解这一点是否合理?如果允许,分配肯定会修改它们,并且防止这恰好是const的要点。或者,如果您更喜欢引用权限,C2011 6.3.2.1/1指定如果结构类型具有任何const成员,则该类型的左值表达式不可修改。

听起来你对整个结构赋值的语义感到困惑。如果将一个结构分配给另一个结构,则不会将一个结构替换为另一个结构;而是将一个结构的复制到另一个结构中。这与简单类型的分配完全类似,例如const

你问,

  

如何实现以下目标:

     
      
  • 创建一个"不可变的" vector2 struct
  •   

在可能的范围内,您已经知道如何做到这一点。如果您创建了所有成员int,则无法通过类型const的表达式修改它们。然而,正如我之前所说,这并不能赋予绝对的不变性。 C没有这样的东西。

  
      
  • 创建一个多边形结构,其点或计数成员不能被更改,但点所指向的东西可以被“转换”。
  •   

我不确定我是否理解交换点的能力如何与您所希望的不可修改性水平一致。当然,如果struct vector2struct vector2个成员,则您无法分配该类型的左值表达式。您仍然可以通过const执行交换,或者通过强制转换为可修改的类型。然而,这些机制确实至少违反了memcpy() - ness的精神。您的编译器可能会警告它们。

您可以考虑将constpoints更改为struct vector2 * const。然后,您可以通过struct vector2 ** const交换(非conststruct vector *个对象:

*points

你对可变性的关注让我想知道你是否来自Java背景;无论哪种方式,这都是Java风格,因为Java中的所有非原语都是引用,它们或多或少都是指针。

但总的来说,我认为你过分关注不变性。 struct vector *temp = poly->points[3]; poly->points[3] = poly->points[2]; poly->points[2] = temp; - 会导致您遇到麻烦,特别是在内存管理方面。考虑不做,至少对你的结构成员本身而言。最多,对函数参数类型使用const限定来表示函数不会修改实际参数,也可能在全局变量上,至少要警告它们有关它们被修改的任何可能性。