【问题标题】:Is this use of an array Undefined Behavior? [duplicate]这是使用数组未定义的行为吗? [复制]
【发布时间】:2015-09-03 11:40:01
【问题描述】:

在我发布的解决方案中,我得到了解决方案包含未定义行为的 cmets。但是,我不明白如何。发布的解决方案的基本内容是:

typedef struct {
    int n;
    int a[1];
} t_x;

void example(void)
{
    int i;
    t_x *t= malloc (sizeof(t_x) + 99*sizeof(int));
    t->n= 100;

    for (i=0; i < t->n; i++)
        t->a[i]= i;

    free(t);
}

UB 的评论集中在数组现在是有 1 个元素(如声明的那样)还是有 100 个元素(如已分配的那样)。

引用的标准部分是6.5.6(指针/int加法)和6.5.2.1(数组下标)

  • "6.5.6 定义了当你添加一个指针和一个整数时会发生什么。生成的指针指向数组的相应元素,如果这样的元素存在,或者指向一个元素超过末尾。否则结果未定义。"

  • “6.5.2.1 定义了 a[n]a+n 方面的含义。因此,如果 a 至少没有 n+1 元素,则不能说 a[n]。”

使用这两个引号,评论者似乎暗示元素 a[99] 将不存在,但是,查看内存布局它显然存在:

请帮助我了解这是否/为什么是 UB 以及我可能期望的 UB 类型。

【问题讨论】:

  • 答案可能取决于您正在处理的 C 标准(C89、C99、C11)。在 C99 及更高版本中,您的代码闻起来很糟糕,因为您应该使用 flexible array member,但我猜它不是 UB
  • 它是 UB,至少按照 C99 之前的标准,访问 a 越界。它的类型为int [1]a[0] 以上的任何访问权限都是未定义的。

标签: c arrays


【解决方案1】:

这是 C99 之前的代码中非常流行的技巧。它适用于许多实现,但严格来说并不合法(因此不可移植)。该标准没有说明t_x 的结构如何在内存中对齐。详情请见C FAQ

C99 引入了灵活长度数组,这是解决此类问题的首选。

【讨论】:

  • +1 表示灵活长度的数组。基本上,OP 需要省略最后一个成员的数组大小(只有int a[];),然后是malloc(sizeof(t_x) + 100*sizeof(int));
  • 谢谢。我确实是 C99 之前的程序员。我知道它不是可移植的,尽管您的链接说“它似乎在所有已知的实现下都可以工作”,因为可能存在内存对齐问题。
  • @SchighSchagh,这不是与我的解决方案完全相同吗?这不会引发同样的内存对齐问题吗?
  • @Paul AFAICT,没有。使用 C99 中明确定义的未在结构中定义数组大小的特殊语法,以非标准/不可移植的方式执行大多数人在 C99 之前所做的事情。
【解决方案2】:

好的,所以问题是,您想为您在代码中定义的表分配内存。在您编写时,此表的大小始终为 1,因此您可以在其中存储一个 int 类型的对象。

如果你想为a动态分配内存,那么你应该:

typedef struct {
int n;
int* a;
} t_x;

然后

t_x someStruct;
someStruct.a=(int*)malloc(numberOfElements*sizeof(int));

【讨论】:

  • 我现在知道了。这不是我的问题。
  • 好的,好的,我现在明白了。
猜你喜欢
  • 2021-11-15
  • 1970-01-01
  • 2018-05-03
  • 2021-12-25
  • 2020-06-15
  • 1970-01-01
相关资源
最近更新 更多