ANSI C/C89结构到int数组[]

ANSI C/C89结构到int数组[],c,arrays,struct,c89,C,Arrays,Struct,C89,有没有一种有效的方法可以将结构赋值/转换为数组,反之亦然 我的结构如下: struct A { int x, y; } struct B { struct A start; struct A end; } 基本上,它们包含开始和结束位置的xy坐标 我需要有效地分配它们,但目前我只能这样做 /* sample code */ struct B b; b.start.x = arr[i]; b.start.y = arr[i]; b.end.x = arr[i]; b.e

有没有一种有效的方法可以将结构赋值/转换为数组,反之亦然

我的结构如下:

struct A {
    int x, y;
}

struct B {
    struct A start;
    struct A end;
}
基本上,它们包含开始和结束位置的xy坐标

我需要有效地分配它们,但目前我只能这样做

/* sample code */
struct B b;
b.start.x = arr[i];
b.start.y = arr[i];
b.end.x = arr[i];
b.end.y = arr[i];


/* I can't do this in ANSI C / C89 as compound literals only allow constants */
b = (struct B) {(struct A) {arr[0], arr[1]}, (struct A) {arr[2], arr[3]}};
我也可以使用复合文本,但当我使用flags-Wall-pedantic-ansi编译时,它在gcc中给了我一个警告

是否有一种方法可以将这4行赋值减少为一行,而不会收到带有上述标志的警告

问候


编辑:修复了复合文字语法

如果您想高效地执行此操作(在一个好的编译器中,第一个代码和第二个代码的效率与您的相同),只需编写:

struct A
{
    int x, y;
};

struct B
{
    struct A start;
    struct A end;
};

void InitA(struct A* s, int x, int y)
{
    s->x = x;
    s->y = y;
}

void InitB(struct B* s, int x1, int y1, int x2, int y2)
{
    InitA(&s->start, x1, y1);
    InitA(&s->end, x2, y2);
}

void InitBFromArray(struct B* s, int *a)
{
    InitB(s, a[0], a[1], a[2], a[3]);
}

int main()
{
    int a[] = { 1, 2, 3, 4 };
    struct B s;
    InitBFromArray(&s, a);
}
int arr[N], i = 0;

b.start.x = arr[i++];
b.start.y = arr[i++];
b.end.x = arr[i++];
b.end.y = arr[i++];
这与您使用的两个示例具有相同的效果。此外,您也可以这样做(但大多数编译器应生成相同的代码:

int arr[N], *p = arr;

b.start.x = *p++;
b.start.y = *p++;
b.end.x = *p++;
b.end.y = *p++;
但是一个好的编译器必须生成与上述示例相同的代码

为什么您认为第一种方法的效率会低于第二种方法

通过复制内存块(甚至用不同的指针重新解释数据)可以获得更高的效率,但这绝对是不可移植的代码


请注意,最后一个示例可能是最有效的,因为您不必复制任何内容,但肯定是不可移植的不正确的不推荐的编码(有时也有效!)

假设您打算编写类似于:

struct B b;
b.start.x = arr[i++];
b.start.y = arr[i++];
b.end.x = arr[i++];
b.end.y = arr[i++];
我会使用四行赋值,而不是复合文字,因为后者看起来太复杂,没有用处。如果我需要多次执行这些赋值,并且循环不可行,那么我会编写一个帮助函数或宏。例如:

function init_b (struct B *b, int *a)
{
  b->start.x = a[0];
  b->start.y = a[1];
  b->end.x = a[2];
  b->end.y = a[3];
}

init_b (&b, arr);

/* or */

#define INIT_B(b,a) do {\
  (b).start.x = (a)[0];\
  (b).start.y = (a)[1];\
  (b).end.x = (a)[2];\
  (b).end.y = (a)[3];\
} while (0)

INIT_B (b, arr);
如果启用了优化的编译器为上述所有代码生成几乎完全相同的代码,我不会感到惊讶

do…while(0)
构造确保宏在用作
for
循环或类似循环的单个语句体时正常工作:

struct B *b;
/* ... */
int i;
for (i = 0; i < /*...*/; i++)
  INIT_B (b[i], arr + 4*i);
structb*B;
/* ... */
int i;
对于(i=0;i
为什么不定义一个宏或函数来执行此操作;或者更进一步,只需执行一个内存复制。请注意,您的“复合文字”在开始处缺少
(结构B)
,在每个嵌套的大括号之前缺少
(结构a)
B=(结构B){(结构a){arr[0],arr[1]},(结构a){arr[2],arr[3]}
By是否有一种有效的方法可以将结构赋值/转换为数组,反之亦然?您是指运行时效率还是最少的代码行数?@arsane Read@JonathanLeffler很抱歉,这会解决问题
struct B *b;
/* ... */
int i;
for (i = 0; i < /*...*/; i++)
  INIT_B (b[i], arr + 4*i);