众所周知,在C90和C99中,有一种叫做结构体hack的技巧,可以在结构体的最后一个成员处使用长度为0的数组。随着C99引入灵活数组成员的方式,我们甚至可以使用[]
以标准的方式来使用它。不幸的是,C++并没有提供这样的构造方法,并且(至少在Clang 3.4中),使用[0]
或[]
编译结构体将会产生编译警告,即使加上了--std=c++11 -pedantic
选项也无济于事:
$ cat test.cpp
struct hack {
char filler;
int things[0];
};
$ clang++ --std=c++11 -pedantic test.cpp
\test.cpp:3:14: warning: zero size arrays are an extension [-Wzero-length-array]
int things[0];
同理
$ cat test.cpp
struct fam {
char filler;
int things[];
};
$ clang++ --std=c++11 -pedantic test.cpp
\test.cpp:3:7: warning: flexible array members are a C99 feature [-Wc99-extensions]
int things[];
我的问题是这样的:假设我想在C++中定义一个包含可变长度数组作为最后一项的结构体,在支持两种方法的编译器下应该怎么做?我应该选择使用结构体技巧中的[0]
(这是一个编译器扩展),还是FAM中的[]
(这是C99的特性)?据我所知,两者都能工作,但我想弄清楚哪个是较小的罪恶?此外,在人们开始建议在结构体中保留指向另行分配的内存块的int*
之前,请注意这不是一个令人满意的答案。我想要分配一个单独的内存块来容纳我的结构体和数组元素。使用std::vector也属于同一类别。如果你想知道为什么我不想使用指针,另一个问题的答案提供了很好的概述。有一些类似的问题,但没有给出答案回答这个特定的问题:
- 是否在C ++中有效使用可变数组成员?:非常相似,但那里的问题是FAM是否在C ++中有效(不是)。我正在寻找选择一种方法或另一种方法的一个好理由。
- 旧“结构体技巧”的符合变体:提出了一种替代方案,但它既不美观,也不总是正确的(如果给结构添加了填充会怎样?)。稍后访问元素也没有像
e.things[42]
这样简洁。
int things[1];
? 对于不会受到结构体奇技淫巧影响的实现,如果有填充的话并没有固有问题,稍后访问元素是完全可以的。 如果你不想浪费一个元素加上可能的填充空间,那么在分配时你只需要多做一点工作。 - nos