在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 */
};
Run Code Online (Sandbox Code Playgroud)
总而言之,我希望一种类型string_t以另一种类型结束,该类型wchararray_t本身是动态大小的 - 其大小存储在其中length.此外,我还想写一个预建的特殊字符串,作为静态数据,这里s1长度为5.
上面的代码假定C99支持/* 1 */./* 2 */据我所知,将子结构包含在更大的结构中,即使是C99标准也不支持 - 但GCC接受它.然而,在/* 3 */GCC放弃:
error: initialization of flexible array member in a nested context
Run Code Online (Sandbox Code Playgroud)
作为一种解决方法,上面的理想代码到目前为止被写为以下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' } }
};
Run Code Online (Sandbox Code Playgroud)
...并且我们使用"s1.b"作为预构建的string_t(并且从不引用"s1.a",这里仅用于s1的静态声明).然而,它打破在最新GCC 4.8,这是因为可优化远的我们的代码部分-显然-任何环路在所述items的一个wchararray_t可以迭代只有一次,因为它是一个长度为1的阵列.
通过给gcc选项来解决这个特殊问题-fno-aggressive-loop-optimizations.它可以或许也没有宣布的长度是固定wchararray_t的items[]排列,使之成为一个动态数组'只是因为’.但是,这种编写代码的方式是一种黑客攻击,我更倾向于以完全不同的方式来解决问题...
(请注意,它是由PyPy生成的所有生成的C代码,而不是手写代码;任何更改都很好,包括它是否需要更改我们在任何地方访问数据的方式,只要"有效"C优化不是防止.)
编辑:用"int []"替换"char []",它不接受双引号语法"hello".这是因为我正在寻找任何阵列类型的解决方案.
不解决:感谢大家的建议.似乎没有干净的方法,所以我实现了hackish解决方案:声明类型k + 1次,一次使用灵活的数组"int items [];" 和其他时间用"int items [N];" 对于所需的各种N值.这需要一些额外的黑客攻击:例如,不使用MSVC的灵活数组(它们的工作方式不同;我没有调查,知道完全相同的语法是否有效); 和GCC遵循C99所说的,并且int items[];对仅包含字段的结构不满意.然而,如果我们添加一个虚拟字段char _dummy[0];... 我很高兴...据我所知,这不是严格的C99 ...
这有点骇人听闻,但这行得通吗?
\n\n#include <stdio.h>\n\ntypedef struct {\n int length;\n int items[]; /* 1 */\n} wchararray_t;\n\ntypedef struct {\n long hash;\n wchararray_t chars; /* 2 */\n int dummy[]; /* hack here */\n} string_t;\n\nstatic string_t s1 = {\n 617862378, { 5 },\n { \'H\', \'e\', \'l\', \'l\', \'o\' } /* 3: changed assignment */\n};\n\nint main(void)\n{\n int i;\n for (i=0; i < 5; ++i) {\n putchar(s1.chars.items[i]);\n }\n putchar(\'\\n\');\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\nGCC 给我警告:
\n\nxx.c:10:22: warning: invalid use of structure with flexible array member [-pedantic]\nxx.c:16:9: warning: initialization of a flexible array member [-pedantic]\nxx.c:16:9: warning: (near initialization for \xe2\x80\x98s1.dummy\xe2\x80\x99) [-pedantic]\nRun Code Online (Sandbox Code Playgroud)\n\n但这似乎有效。
\n\n\n\n编辑:添加一个“填充成员”以确保items[]始终正确对齐怎么样?
#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stddef.h>\n\n/* change to the strictest alignment type */\ntypedef long aligner;\n\ntypedef struct {\n long stuff; /* to show misalignment on 64-bit */\n int length;\n aligner padding;\n int items[];\n} chararray_t;\n\ntypedef struct {\n long hash;\n chararray_t chars;\n int dummy[];\n} string_t;\n\nstatic string_t b1 = {\n 617862378,\n { 42, 5 },\n {-1, -2, -3, -4, -5}\n};\n\nint main(void)\n{\n int i;\n\n printf("sizeof chararray_t: %zu\\n", sizeof(chararray_t));\n printf("offsetof items: %zu\\n", offsetof(chararray_t, items));\n\n printf("sizeof string_t: %zu\\n", sizeof(string_t));\n printf("offsetof dummy: %zu\\n", offsetof(string_t, dummy));\n\n for (i=0; i < 5; ++i) {\n printf("%d ", b1.chars.items[i]);\n }\n putchar(\'\\n\');\n for (i=0; i < 5; ++i) {\n printf("%d ", b1.dummy[i]);\n }\n putchar(\'\\n\');\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n当我运行上面的代码时,我似乎得到了正确的答案:
\n\nsizeof chararray_t: 24\noffsetof items: 24\nsizeof string_t: 32\noffsetof dummy: 32\n-1 -2 -3 -4 -5 \n-1 -2 -3 -4 -5 \nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2846 次 |
| 最近记录: |