在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
,在另一种类型的端部wchararray_t
即本身动态调整-其大小被存储在length
。 此外,我也喜欢写预建特定的字符串,如静态数据,这里s1
长度为5的。
上面的代码承担C99支持/* 1 */
。 列入子进入大结构中/* 2 */
是,据我了解,甚至没有得到C99标准的支持-但GCC接受它。 然而,在/* 3 */
GCC放弃:
error: initialization of flexible array member in a nested context
作为一种变通方法,理想的代码上面是迄今为止写为下面的技巧,这“种作品”:
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[]
阵列,使其成为一个动态数组‘只是因为’。 然而,这种方式编写代码是这样的,我宁愿一个完全不同的方式来解决这个问题一个黑客...
(请注意,它是所有生成的C代码由PyPy产生的,而不是手工编写代码;任何改变是好的,包括是否需要改变我们随时随地访问数据的方式,只要在“有效” C优化不防止。)
编辑:更换“的char []”和“INT []”,不接受双引号语法"hello"
。 这是因为我在寻找任何数组类型的解决方案。
没有解决:感谢大家对你的建议。 似乎没有干净的方式,所以我已经实现了的hackish溶液:声明类型的柔性阵列K + 1次,一次“INT项[];” 和第k其他时间用“INT项[N];” 为是需要的N的各种值。 这需要一些额外的黑客:如不使用灵活的阵列来MSVC(他们的工作方式有所不同,我没有调查就知道,如果完全一样的语法将工作); 和GCC遵循什么C99说,是不是很满意,将包含结构int items[];
因为只有场。 然而高兴,如果我们添加了一个空场char _dummy[0];
......这不是严格C99,据我知道...
Answer 1:
它的hackish,但可以这项工作?
#include <stdio.h>
typedef struct {
int length;
int items[]; /* 1 */
} wchararray_t;
typedef struct {
long hash;
wchararray_t chars; /* 2 */
int dummy[]; /* hack here */
} string_t;
static string_t s1 = {
617862378, { 5 },
{ 'H', 'e', 'l', 'l', 'o' } /* 3: changed assignment */
};
int main(void)
{
int i;
for (i=0; i < 5; ++i) {
putchar(s1.chars.items[i]);
}
putchar('\n');
return 0;
}
海湾合作委员会给我的警告:
xx.c:10:22: warning: invalid use of structure with flexible array member [-pedantic]
xx.c:16:9: warning: initialization of a flexible array member [-pedantic]
xx.c:16:9: warning: (near initialization for ‘s1.dummy’) [-pedantic]
但它似乎工作。
参考
编辑 :如何补充说,确保了“垫元件” items[]
总是正确对齐?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
/* change to the strictest alignment type */
typedef long aligner;
typedef struct {
long stuff; /* to show misalignment on 64-bit */
int length;
aligner padding;
int items[];
} chararray_t;
typedef struct {
long hash;
chararray_t chars;
int dummy[];
} string_t;
static string_t b1 = {
617862378,
{ 42, 5 },
{-1, -2, -3, -4, -5}
};
int main(void)
{
int i;
printf("sizeof chararray_t: %zu\n", sizeof(chararray_t));
printf("offsetof items: %zu\n", offsetof(chararray_t, items));
printf("sizeof string_t: %zu\n", sizeof(string_t));
printf("offsetof dummy: %zu\n", offsetof(string_t, dummy));
for (i=0; i < 5; ++i) {
printf("%d ", b1.chars.items[i]);
}
putchar('\n');
for (i=0; i < 5; ++i) {
printf("%d ", b1.dummy[i]);
}
putchar('\n');
return 0;
}
当我运行上面,我似乎得到正确的答案:
sizeof chararray_t: 24
offsetof items: 24
sizeof string_t: 32
offsetof dummy: 32
-1 -2 -3 -4 -5
-1 -2 -3 -4 -5
Answer 2:
回答我的问题写下来。 另一个黑客将建立在阿洛克的建议,这可能会给一个偶尔假对准的顶部---然后确定由init-时间码对齐。 这假定大多数在程序中使用这种类型的发生正确对齐。 码:
typedef struct {
long stuff; /* to show misalignment on 64-bit */
int length;
int items[];
} chararray_t;
typedef struct {
long hash;
chararray_t chars;
int dummy[];
} string_t;
static string_t b1 = {
617862378,
{ 42, 5 },
{-1, -2, -3, -4, -5}
};
/* same with b2 .. b6 */
void fixme(void) {
/* often compares as equal, and the whole function is removed */
if (offsetof(string_t, dummy) !=
offsetof(string_t, chars) + offsetof(chararray_t, items)) {
static string_t *p_array[] = { &b1, &b2, &b3, &b4, &b5, &b6 };
string_t *p;
int i;
for (i=0; i<6; i++) {
p = p_array[i];
memmove(p->chars.items, p->dummy, p->chars.length * sizeof(int));
}
}
}
Answer 3:
#include <stdio.h>
typedef struct {
int length;
char items[]; /* 1 */
} chararray_t;
typedef struct {
long hash;
chararray_t chars; /* 2 */
} string_t;
/*static string_t s1 = {
617862378,
{ 5, { 'H', 'e', 'l', 'l', 'o' } } // 3
};*/
static string_t s1 =
{
617862378,
{6,"Hello"} /* 3 */
};
int main()
{
printf("%d %d %s\n",s1.hash,s1.chars.length,s1.chars.items);
return 0;
}
加1为空字符等瞧! :)
编辑,也适用于2层嵌套(GCC 4.8.0)
#include <stdio.h>
typedef struct {
int length;
char items[]; /* 1 */
} chararray_t;
typedef struct {
long hash;
chararray_t chars; /* 2 */
} string_t;
typedef struct {
long number;
string_t arr;
}experiment_t;
static experiment_t s1 =
{
617862378,
{786,{6,"Hello"}} /* 3 */
};
int main()
{
printf("%d %d %d %s\n",s1.number,s1.arr.hash,s1.arr.chars.length,s1.arr.chars.items);
return 0;
}
----------编辑2 ------------------实测值周围的限制的方式Ç初始化结构中阵列
最终代码::
#include <stdio.h>
typedef struct {
int length;
int *items; /* 1 */
} intarray_t;
typedef struct {
long hash;
intarray_t chars; /* 2 */
int dummy[2];
} string_t;
/*string_t s1 =
{
617862378,
{
6,
{1,2,3,4,5,6}
},
{
0,0
}
};*/
string_t s1 = {617862378,{},{0,0}};
int main()
{
int i=0;
intarray_t t1 = {.length = 6, .items = (int[6]){1,2,3,4,5,6}};
s1.chars = t1;
printf("%d %d\n",s1.hash,s1.chars.length);
while(i<s1.chars.length)
{
printf("%d",s1.chars.items[i]);
i++;
}
putchar('\n');
return 0;
}
Answer 4:
我认为有一些原因保持字符串“内部”结构,并且要保存一个字符,通过不与C-字符串初始化。
但是,如果没有,你可以这样做:
typedef struct {
int length;
char *items; /* 1 */
} chararray_t;
typedef struct {
long hash;
chararray_t chars; /* 2 */
} string_t;
static string_t s1 = {
617862378,
{ 5, "Hell" } /* 3 */
};
s1.chars.items[4] = 'o' ;
看起来你可以做工会伎俩,但类型转换呢?
#include <stdio.h>
typedef struct { int length; int items[]; } 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; } s5 = {
617862378,
{ 5, { 'H', 'e', 'l', 'l', 'o' } }
};
string_t *s1 = (string_t*) &s5 ;
int main( int argc, char *argv[])
{
for( int i = 0 ; i < s1->chars.length ; i++ )
{
printf ( "%c", s1->chars.items[i] );
}
printf( "\n" );
}
文章来源: Dynamic array and prebuilt data