Initializing a Global Struct in C

若如初见. 提交于 2020-05-23 05:40:09

问题


What is the best way to accomplish the following in 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!


回答1:


Why not use static initialization?

struct A a = { 42 };



回答2:


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.




回答3:


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




回答4:


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.

If you have more complicated setup, I would strongly advocate that you use 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:

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_init and 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.




回答5:


For curious people who also use 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.

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.




回答6:


You can't call a function as an initiliazer. You need to call it inside main.



来源:https://stackoverflow.com/questions/2521927/initializing-a-global-struct-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!