如何在 C 中声明后初始化结构数组
How to initialize array of structures after declaration in C
有没有办法在声明后初始化整个结构数组(可能使用复合文字)?
typedef struct
{
int a;
int b;
} tStruct;
/* Array of structures in declared in global scope, but not initialized */
tStruct myStruct[3];
void init()
{
/* We want to initizlize the array with specific values*/
/* using compound literals to initialize the whole array doesn't work */
myStruct = (tStruct[])
{
{1, 2},
{3, 4},
{5, 6}
};
}
数组不是 R 值,因此您不能通过赋值复制它们。但是你可以使用 memcpy
#include <string.h>
void init(void)
{
memcpy(&myStruct,(tStruct[]) { {1, 2}, {3, 4}, {5, 6} }, sizeof(myStruct));
}
优化编译器生成的代码应该不会比你得到的代码差多少
void init2(void)
{
myStruct[0] = (tStruct){1,2};
myStruct[1] = (tStruct){3,4};
myStruct[2] = (tStruct){5,6};
}
或
void init3(void)
{
myStruct[0].a = 1, myStruct[0].b = 2;
myStruct[1].a = 3, myStruct[1].b = 4;
myStruct[2].a = 5, myStruct[1].b = 6;
}
Gcc 和 clang 能够很好地省略不必要的复合变量,例如直接分配单个组件。
https://gcc.godbolt.org/z/j9f37j
memcpy
方法的最大缺点是它有点脆弱且类型不安全(如果违反了非强制类型兼容性,可能会导致越界 reads/writes)。
如果你的 C 方言有 __typeof,那么通过一些宏技巧你应该能够几乎绕过这个 C 语言限制:
#include <string.h>
#define assignAnything(DestPtr,SrcPtr) ((void)((__typeof(SrcPtr)){0} = (__typeof(DestPtr)){0}) /*typecheck*/, memcpy(DestPtr, SrcPtr, sizeof(*(DestPtr))))
/* A Ptr-less version:
#define assignAnything2(Dest,Src) ((void)((__typeof(&(Src))){0} = (__typeof(&(Dest))){0}), memcpy(&(Dest), &(__typeof(Src)){Src}, sizeof(Dest)))
doesn't always work, unfortunately */
int main()
{
int d[3][2][1]={0};
int const s[3][2][1] = {0};
assignAnything(&d,&s); //works
#if NOPE
assignAnything(&s,&d); //will (correctly) compile-time fail because s has more qualifs (const) than d
#endif
}
不,这不起作用,因为您不能将一个数组分配给另一个数组。
但您可以使用 memcpy
来绕过它
void init()
{
tStruct data[3] = {
{1, 2},
{3, 4},
{5, 6}
};
memcpy(mystruct, data, sizeof(mystruct));
}
但是,注意数据的大小必须完全匹配。
对于数组,复合文字只对语句声明起作用。之后您必须使用单独的赋值、循环、memcpy() 或 memset() 来初始化数组和结构。
示例,获得相同的结果:
typedef struct
{
int a;
int b;
} tStruct;
/* Array of structures in declared in global scope, but not initialized */
tStruct myStruct[3];
void init()
{
/* Initizlize the array with specific values*/
int i;
const tStruct second_element = { 3, 4 };
// member by member...
myStruct[0].a = 1;
myStruct[0].b = 2;
// using struct copy.
myStruct[1] = second_element;
// or a loop...
for (i = 2; i < 3; ++i) // I know, there are only 3 elmments, but you get
// the idea..
{
myStruct[i].a = (2 * i) + 1;
myStruct[i].b = myStruct[i].a + 1;
}
}
有没有办法在声明后初始化整个结构数组(可能使用复合文字)?
typedef struct
{
int a;
int b;
} tStruct;
/* Array of structures in declared in global scope, but not initialized */
tStruct myStruct[3];
void init()
{
/* We want to initizlize the array with specific values*/
/* using compound literals to initialize the whole array doesn't work */
myStruct = (tStruct[])
{
{1, 2},
{3, 4},
{5, 6}
};
}
数组不是 R 值,因此您不能通过赋值复制它们。但是你可以使用 memcpy
#include <string.h>
void init(void)
{
memcpy(&myStruct,(tStruct[]) { {1, 2}, {3, 4}, {5, 6} }, sizeof(myStruct));
}
优化编译器生成的代码应该不会比你得到的代码差多少
void init2(void)
{
myStruct[0] = (tStruct){1,2};
myStruct[1] = (tStruct){3,4};
myStruct[2] = (tStruct){5,6};
}
或
void init3(void)
{
myStruct[0].a = 1, myStruct[0].b = 2;
myStruct[1].a = 3, myStruct[1].b = 4;
myStruct[2].a = 5, myStruct[1].b = 6;
}
Gcc 和 clang 能够很好地省略不必要的复合变量,例如直接分配单个组件。
https://gcc.godbolt.org/z/j9f37j
memcpy
方法的最大缺点是它有点脆弱且类型不安全(如果违反了非强制类型兼容性,可能会导致越界 reads/writes)。
如果你的 C 方言有 __typeof,那么通过一些宏技巧你应该能够几乎绕过这个 C 语言限制:
#include <string.h>
#define assignAnything(DestPtr,SrcPtr) ((void)((__typeof(SrcPtr)){0} = (__typeof(DestPtr)){0}) /*typecheck*/, memcpy(DestPtr, SrcPtr, sizeof(*(DestPtr))))
/* A Ptr-less version:
#define assignAnything2(Dest,Src) ((void)((__typeof(&(Src))){0} = (__typeof(&(Dest))){0}), memcpy(&(Dest), &(__typeof(Src)){Src}, sizeof(Dest)))
doesn't always work, unfortunately */
int main()
{
int d[3][2][1]={0};
int const s[3][2][1] = {0};
assignAnything(&d,&s); //works
#if NOPE
assignAnything(&s,&d); //will (correctly) compile-time fail because s has more qualifs (const) than d
#endif
}
不,这不起作用,因为您不能将一个数组分配给另一个数组。
但您可以使用 memcpy
来绕过它
void init()
{
tStruct data[3] = {
{1, 2},
{3, 4},
{5, 6}
};
memcpy(mystruct, data, sizeof(mystruct));
}
但是,注意数据的大小必须完全匹配。
对于数组,复合文字只对语句声明起作用。之后您必须使用单独的赋值、循环、memcpy() 或 memset() 来初始化数组和结构。
示例,获得相同的结果:
typedef struct
{
int a;
int b;
} tStruct;
/* Array of structures in declared in global scope, but not initialized */
tStruct myStruct[3];
void init()
{
/* Initizlize the array with specific values*/
int i;
const tStruct second_element = { 3, 4 };
// member by member...
myStruct[0].a = 1;
myStruct[0].b = 2;
// using struct copy.
myStruct[1] = second_element;
// or a loop...
for (i = 2; i < 3; ++i) // I know, there are only 3 elmments, but you get
// the idea..
{
myStruct[i].a = (2 * i) + 1;
myStruct[i].b = myStruct[i].a + 1;
}
}