是否有一种有效的方法将结构转换/转换为数组,反之亦然?
我的结构如下:
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行赋值减少到只有一行而没有得到上述标志的警告。
此致
编辑:修复复合文字语法
答案 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);