这是使用数组未定义的行为吗?

在我发布的解决方案中,我得到的评论是解决方案包含未定义的行为。 但是,我不知道怎么做。 发布的解决方案的基础是:

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 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类型。

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

C99引入了灵活长度arrays,这是这种问题的首选。

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

如果要为a动态分配内存,则应该:

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

然后

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