From 声明灵活数组成员时使用正确的语法 https://wiki.sei.cmu.edu/confluence/display/c/DCL38-C.+Use+the+correct+syntax+when+declaring+a+flexible+array+member它说当malloc
用于标题和灵活数据时data[1]
被黑客入侵struct
,
此示例在访问其他任何元素时具有未定义的行为
比数据数组的第一个元素。 (参见 C 标准,6.5.6。)
因此,编译器可以生成不返回
访问数据的第二个元素时的预期值。
我查阅了 C 标准 6.5.6,但看不出这会如何产生未定义的行为。我使用了一种我喜欢的模式,其中标题后面隐式跟随数据,使用相同类型的malloc
,
#include <stdlib.h> /* EXIT malloc free */
#include <stdio.h> /* printf */
#include <string.h> /* strlen memcpy */
struct Array {
size_t length;
char *array;
}; /* +(length + 1) char */
static struct Array *Array(const char *const str) {
struct Array *a;
size_t length;
length = strlen(str);
if(!(a = malloc(sizeof *a + length + 1))) return 0;
a->length = length;
a->array = (char *)(a + 1); /* UB? */
memcpy(a->array, str, length + 1);
return a;
}
/* Take a char off the end just so that it's useful. */
static void Array_to_string(const struct Array *const a, char (*const s)[12]) {
const int n = a->length ? a->length > 9 ? 9 : (int)a->length - 1 : 0;
sprintf(*s, "<%.*s>", n, a->array);
}
int main(void) {
struct Array *a = 0, *b = 0;
int is_done = 0;
do { /* Try. */
char s[12], t[12];
if(!(a = Array("Foo!")) || !(b = Array("To be or not to be."))) break;
Array_to_string(a, &s);
Array_to_string(b, &t);
printf("%s %s\n", s, t);
is_done = 1;
} while(0); if(!is_done) {
perror(":(");
} {
free(a);
free(b);
}
return is_done ? EXIT_SUCCESS : EXIT_FAILURE;
}
Prints,
<Foo> <To be or >
合规解决方案使用C99
灵活的数组成员。该页面还说,
声明灵活数组时未能使用正确的语法
尽管语法不正确,但成员可能会导致未定义的行为
将适用于大多数实现。
从技术上讲,这是否C90
代码也会产生未定义的行为吗?如果不是,有什么区别? (或者卡内基梅隆维基百科是不正确的?)导致此方法不起作用的实现因素是什么?