动态数组和预置的数据(Dynamic array and prebuilt data)

2019-08-31 06:09发布

在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_titems[]阵列,使其成为一个动态数组‘只是因为’。 然而,这种方式编写代码是这样的,我宁愿一个完全不同的方式来解决这个问题一个黑客...

(请注意,它是所有生成的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
标签: c arrays static