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*…*/;i++)
初始B(B[i],arr+4*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);