在 C 中,我正在尝试执行以下操作:
typedef struct {
int length;
int items[]; /* 1 */
} wchararray_t;
typedef struct {
long hash;
wchararray_t chars; /* 2 */
} string_t;
static string_t s1 = {
617862378,
{ 5, { 'H', 'e', 'l', 'l', 'o' } } /* 3 */
};
简而言之,我想要一种以另一种本身动态调整大小的类型string_t
结尾的类型——它的大小存储在. 此外,我还想编写一个预先构建的特定字符串,作为静态数据,这里长度为 5。wchararray_t
length
s1
上面的代码假定 C99 支持/* 1 */
. /* 2 */
据我了解,即使 C99 标准也不支持将子结构包含在更大的结构中,但 GCC 接受了它。然而,在/* 3 */
GCC 放弃了:
error: initialization of flexible array member in a nested context
作为一种解决方法,到目前为止,上面的理想代码编写为以下 hack,“有点工作”:
typedef struct { int length; int items[1]; } wchararray_t;
typedef struct { long hash; wchararray_t chars; } string_t;
typedef struct { int length; int items[5]; } wchararray_len5_t;
typedef struct { long hash; wchararray_len5_t chars; } string_len5_t;
static union { string_len5_t a; string_t b; } s1 = {
617862378,
{ 5, { 'H', 'e', 'l', 'l', 'o' } }
};
...并且我们将使用“s1.b”作为预构建的 string_t(并且永远不要引用“s1.a”,它仅用于 s1 的静态声明)。然而,它在最新的 GCC 4.8 中中断,它优化了我们的部分代码,因为——显然——任何items
对 a 的wchararray_t
循环都只能迭代一次,因为它是一个长度为 1 的数组。
通过为 gcc 提供选项来解决此特定问题-fno-aggressive-loop-optimizations
。它也可以通过不声明数组中的长度来修复wchararray_t
,items[]
使其成为“仅仅因为”的动态数组。但是,这种编写代码的方式是一种 hack,我宁愿用一种完全不同的方式来解决这个问题......
(请注意,这都是由 PyPy 生成的 C 代码,而不是手写代码;任何更改都可以,包括是否需要更改我们在任何地方访问数据的方式,只要“有效”的 C 优化不是防止。)
编辑:将“char[]”替换为“int[]”,它不接受双引号语法"hello"
。这是因为我正在寻找任何数组类型的解决方案。
未解决:感谢大家的建议。似乎没有干净的方法,所以我实现了骇人听闻的解决方案:声明类型 k+1 次,一次使用灵活的数组“int items[];” 其他 k 次使用“int items[N];” 对于所需的各种 N 值。这需要一些额外的技巧:例如不为 MSVC 使用灵活的数组(它们在那里的工作方式不同;我没有调查是否知道完全相同的语法是否可以工作);int items[];
并且 GCC 遵循 C99 所说的内容,并且对仅包含字段的结构不满意。然而,如果我们添加一个虚拟字段会很高兴char _dummy[0];
......据我所知,这不是严格意义上的 C99......