C语言 用 C 初始化全局结构
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2521927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Initializing a Global Struct in C
提问by Scott
What is the best way to accomplish the following in C?
在 C 中完成以下任务的最佳方法是什么?
#include <stdio.h>
struct A
{
int x;
};
struct A createA(int x)
{
struct A a;
a.x = x;
return a;
}
struct A a = createA(42);
int main(int argc, char** argv)
{
printf("%d\n", a.x);
return 0;
}
When I try to compile the above code, the compiler reports the following error:
当我尝试编译上述代码时,编译器报告以下错误:
"initializer element is not constant"
“初始化元素不是常量”
The bad line is this one:
不好的一行是这样的:
struct A a = createA(42);
Can someone explain what is wrong? I'm not very experienced in C. Thanks!
有人可以解释一下有什么问题吗?我在 C 方面不是很有经验。谢谢!
采纳答案by BjoernD
Why not use static initialization?
为什么不使用静态初始化?
struct A a = { 42 };
回答by nategoose
struct A a = { .x = 42 };
More members:
更多会员:
struct Y {
int r;
int s;
int t;
};
struct Y y = { .r = 1, .s = 2, .t = 3 };
You could also do
你也可以这样做
struct Y y = { 1, 2, 3 };
The same thing works for unions, and you don't have to include all of the members or even put them in the correct order.
同样的事情也适用于工会,您不必包括所有成员,甚至不必将他们按正确的顺序排列。
回答by JaredPar
The problem here is that global / file static variables in C must have a value known at compile time. This means you can't use a user defined function to initialize the value. It must be a constant expression
这里的问题是 C 中的全局 / 文件静态变量必须具有在编译时已知的值。这意味着您不能使用用户定义的函数来初始化该值。它必须是一个常量表达式
回答by Michael Aaron Safyan
You cannot invoke functions in static initialization like that. In your example, you can simply use:
您不能像那样在静态初始化中调用函数。在您的示例中,您可以简单地使用:
struct A a = {42};
If you have a more complicated setup, you will need to provide a library construction and library destruction function that you force users of your library to call (assuming you want to be portable), or you will have to use C++ and take advantage of constructors/destructors, or you will have to take advantage of the non-standard and non-portable __attribute__((constructor)) to create a function that is run on startup to initialize it.
如果你有一个更复杂的设置,你将需要提供一个库构造和库销毁函数,你强迫你的库的用户调用(假设你想是可移植的),或者你将不得不使用 C++ 并利用构造函数/析构函数,否则您将不得不利用非标准和不可移植的 __attribute__((constructor)) 创建一个在启动时运行的函数来初始化它。
If you have more complicated setup, I would strongly advocate that you use C++:
如果您有更复杂的设置,我强烈建议您使用 C++:
class A
{
A(){
// can do initialization in the constructor
}
// ...
};
A a;
However, if you need to stick with pure C, the portable thing to do is use something like:
但是,如果您需要坚持使用纯 C,那么可移植的方法是使用以下内容:
typedef void* mylibrary_attr_t; typedef void* mylibrary_t; #ifdef __cplusplus # define EXTERNC extern "C" #else # define EXTERNC #endif EXTERNC int mylibrary_attr_init(mylibrary_attr_t*); EXTERNC int mylibrary_attr_setparam1(mylibrary_attr_t,int); EXTERNC int mylibrary_attr_setparam2(mylibrary_attr_t,double); // .. more functions for various attributes used by library EXTERNC void mylibrary_attr_destroy(mylibrary_attr_t*); EXTERNC int mylibrary_init(mylibrary_t*,mylibrary_attr_t); EXTERNC void mylibrary_destroy(mylibrary_t*); // functions that use mylibrary_t // ...
Basically, in the above, you would initialize your library with mylibrary_initand teardown your library using mylibrary_destroy. The functions using your library would require an initialized instance of mylibrary_t, and so the person who created the main function would be responsible for invoking mylibrary_init. It is also good to make the initialization function dependent on an "attributes" parameter that can be replaced with 0 or NULL as a default. That way, if you extend your library and need to accept configuration options, it is available to you. That's more a design than technical approach, though.
基本上,在上面,您将mylibrary_init使用mylibrary_destroy. 使用您的库的函数需要一个初始化的 实例mylibrary_t,因此创建主函数的人将负责调用mylibrary_init. 使初始化函数依赖于“属性”参数也很好,该参数可以替换为 0 或 NULL 作为默认值。这样,如果您扩展您的库并需要接受配置选项,您就可以使用它。不过,这更像是一种设计而不是技术方法。
回答by Pyjong
For curious people who also use MSVC:
对于也使用 MSVC 的好奇的人:
In C it is possible to run initialization functions before main just as it is possible in C++ (of course it is, how would C++ do it if it wasn't possible in C), however it may be somewhat confusing if you haven't read how does your runtime library work.
在 C 中,可以在 main 之前运行初始化函数,就像在 C++ 中一样(当然是的,如果在 C 中不可能,C++ 将如何做到这一点),但是如果您没有这样做,可能会有些混乱阅读您的运行时库是如何工作的。
Long story short:
长话短说:
#pragma section(".CRT$XIU",long,read)
int
init_func ()
{
// initialization
return 0; // return 0 is mandatory
}
__declspec(allocate(".CRT$XIU"))
int (*global_initializer)() = init_func;
So it's not as compact source text as in C++, but it can be done. Also, before using I recommend to understand PE format first, then read crt\src\crt0.c and crt\src\crt0dat.c (search for _cinit in both files) in your MSVC installation directory so you know what is going on.
所以它不像在 C++ 中那样紧凑的源文本,但它可以做到。另外,在使用之前,我建议先了解 PE 格式,然后阅读 MSVC 安装目录中的 crt\src\crt0.c 和 crt\src\crt0dat.c(在两个文件中搜索 _cinit),以便您知道发生了什么。
回答by kgiannakakis
You can't call a function as an initiliazer. You need to call it inside main.
您不能将函数作为初始化程序调用。您需要在 main 中调用它。

