Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 动态数组和预构建数据_C_Arrays_Static - Fatal编程技术网

C 动态数组和预构建数据

C 动态数组和预构建数据,c,arrays,static,C,Arrays,Static,在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' } }

在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\u t
,它以另一个类型
wchararray\u t
结尾,该类型本身是动态大小的——它的大小存储在
length
中。此外,我还想编写一个预构建的特定字符串,作为静态数据,在这里
s1
长度为5

以上代码假定C99支持
/*1*/
。据我所知,甚至C99标准都不支持将下部结构包含在
/*2*/
的更大结构中,但GCC接受它。然而,在
/*3*/
GCC放弃:

error: initialization of flexible array member in a nested context
作为一种变通方法,到目前为止,上述理想代码被编写为以下hack,即“工作类型”:

…我们将使用“s1.b”作为预构建字符串(并且永远不要引用“s1.a”,它在这里仅用于s1的静态声明)。然而,它突破了最新的GCC4.8,它优化了我们的部分代码,因为很明显,
wchararray\u t
项上的任何循环都只能迭代一次,因为它是一个长度为1的数组

通过向gcc提供选项
-fno adgressive loop optimizations
,可以解决这个特殊问题。也可以通过不在
wchararray\u t
items[]
数组中声明长度来修复它,使其成为动态数组“仅仅因为”。然而,这种编写代码的方法是一种非常糟糕的方法,我更喜欢一种完全不同的方法来解决这个问题

(请注意,所有这些都是PyPy生成的C代码,而不是手工编写的代码;只要不阻止“有效”的C优化,任何更改都可以,包括是否需要更改我们在任何地方访问数据的方式。)

编辑:将“char[]”替换为“int[]”,它不接受双引号语法
“hello”
。这是因为我正在为任何数组类型寻找解决方案


未解决:谢谢大家的建议。似乎没有干净的方法,所以我实现了一个骇人的解决方案:声明类型k+1次,一次使用灵活的数组“int items[];”,另一次使用“int items[N];”来声明所需的各种N值。这需要一些额外的技巧:例如,不为MSVC使用灵活的数组(它们在那里的工作方式不同;我没有调查是否完全相同的语法可以工作);GCC遵循C99的说法,对包含
int项[]的结构不满意作为唯一字段。但是,如果我们添加一个虚拟字段
char\u dummy[0],它会很高兴。。。据我所知,这并不是严格意义上的C99…

我假设有一些理由将字符串保留在结构中,并且您希望通过不使用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" );
}
#包括
typedef结构{int length;int items[];}wchararray\u t;
typedef结构{long hash;wchararray\u t chars;}string\u t;
typedef结构{int length;int items[5];}wchararray\u len5\u t;
typedef结构{long hash;wchararray_len5_t chars;}string_len5_t;
静态并集{string_len5_t a;string_t b;}s5={
617862378,
{5,{H',e',l',l',o'}
};
字符串s1=(字符串)和s5;
int main(int argc,char*argv[])
{
对于(int i=0;ichars.length;i++)
{
printf(“%c”,s1->chars.items[i]);
}
printf(“\n”);
}
#包括
类型定义结构{
整数长度;
字符项[];/*1*/
}查拉雷;
类型定义结构{
长散列;
chararray\u t chars;/*2*/
}弦乐;
/*静态字符串\u t s1={
617862378,
{5,{H',e',l',l',o'}//3
};*/
静态字符串s1=
{
617862378,
{6,“你好”}/*3*/
};
int main()
{
printf(“%d%d%s\n”,s1.hash,s1.chars.length,s1.chars.items);
返回0;
}
为空字符添加1,et voila!:)

编辑,也适用于2级嵌套(GCC 4.8.0)

#包括
类型定义结构{
整数长度;
字符项[];/*1*/
}查拉雷;
类型定义结构{
长散列;
chararray\u t chars;/*2*/
}弦乐;
类型定义结构{
长数;
字符串到达;
}实验;
静态实验1=
{
617862378,
{786,{6,“你好”}/*3*/
};
int main()
{
printf(“%d%d%d%s\n”,s1.number,s1.arr.hash,s1.arr.chars.length,s1.arr.chars.items);
返回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;
}
#包括
类型定义结构{
整数长度;
int*项;/*1*/
}无阵列;
类型定义结构{
长散列;
无阵列字符;/*2*/
int-dummy[2];
}弦乐;
/*字符串s1=
{
617862378,
{
6.
{1,2,3,4,5,6}
},
{
0,0
}
};*/
字符串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);

虽然(我这很粗糙,但这行得通吗

#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;
}
但它似乎奏效了

编辑:添加一个“填充成员”来确保
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;
}

回答我自己的问题并将其写下来。另一种黑客方法是在Alok建议的基础上进行构建,该建议可能会偶尔给出虚假的对齐方式,然后通过初始化时间代码修复对齐方式。这假设程序中使用的绝大多数此类类型恰好正确对齐。代码:

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));
        }
    }
}
typedef结构{
long stuff;/*显示64位上的未对齐*/
整数长度;
国际项目[];
}查拉雷;
类型定义结构{
长散列;
chararray_t chars;
int-dummy[];
}弦乐;
静态字符串\u t b1={
617862378,
{ 42, 5 },
{-1, -2, -3, -4, -5}
};
/*与b2..b6相同*/
void fixme(void){
/*经常
#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]
#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 
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));
        }
    }
}