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

时间:2014-08-10 02:54:13

标签: 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.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行赋值减少到只有一行而没有得到上述标志的警告。

此致

编辑:修复复合文字语法

3 个答案:

答案 0 :(得分:3)

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);
}

答案 1 :(得分:0)

我想有效地完成它(第一个代码和第二个代码在一个好的编译器中具有相同的效率,因为你正在做同样的事情)只写:

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 *ptr = (struct B *)arr;  /* or arr + 4*i */
/* now use ptr->start.x, ptr->start.y, ptr->end.x and ptr->end.y */

请注意,最后一个示例可能是效率最高的,因为您不必复制任何内容,但最终不可移植不正确和<强>不推荐编码。 (有时工作!)

答案 2 :(得分:0)

假设您打算写一些类似于:

的内容
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);