Home > Enterprise >  How to declare global static array of strings and const non-POD data in C ?
How to declare global static array of strings and const non-POD data in C ?

Time:11-05

I need to make constant global array of strings in file "misc.h". I don't really understand how this should be done. If it was just one string, I would have declared it like this:

// misc.h
extern const char* str;

// misc.cpp
//static const char* str = "some sring"; invalid because of extern linkage 
const char* str = "some string";

If i want an array of strings, first thing that comes to mind is:

extern const char* strings[];

The size of array is known at compile-time and usually would have been deduced by the compiler from initializer, but here the initialization would lie (as of my understandnig) in another compilation unit, misc.cpp (the array is pretty big and i don't want to re-count it's size every time i add features and recompile my code). How should I handle this situation?
Edit: all of the strings and everything in this question is immutable and does not need any functionality from standard library.


The second question on the same topic is how should I declare constant hash map (const QHash, more specifially) in the same file? I also need it to be global static. I am not building a library, and this hash map servers the core functionality of my application, so making it global static should be appropriate. I know there is Q_GLOBAL_STATIC macro, but it is used for preventing data races, and my hash map is read-only by definition. I've heard about inline variables, but I don't really understand them - should I try to dig there? What would be the best way to do declare and use such variable?

CodePudding user response:

For any immutable global constant c of type C in C , you can simply write

const C c = /*initializer*/;

in the header. const variables have internal linkage by default. It will be a different c in each translation unit and there won't be any redefinition error. (Beware however that this is different in C.)

Even better would be

constexpr C c = /*initializer*/;

assuming the type C supports the constant expression initialization. This guarantees that no initialization will happen at runtime and that the variable can be used in other constant expressions. With just const there may be dynamic initialization at runtime, which can potentially lead to issues with initialization order, although that is less of a concern inside a single translation unit than across multiple. (constexpr implies const on the type.)

In few occasions the type may support constant expression initialization, but not constant destruction. In that case one can still use

constinit const C c = /*initializer*/;

constinit will cause the declaration to fail if constant initialization can't be performed, while still allowing non-constant destruction. (It does not imply const on the type though, so that must be added explicitly.)

If constant initialization is not possible and order of initialization a potential concern, a global variable shouldn't be used at all. Instead local static variables in a function can be used.

If you need to rely on c being the same object in each translation unit, then you can add inline to the definition in the header.


For an array of strings:

constexpr const char* c[] = {"string1", "string2", "string3"};

or

constexpr std::array c = {"string1", "string2", "string3"};

(Or any other variation of declaration syntax for these types. You could also use std::string, but that doesn't currently support constant initialization as of C 23. Variations of the two declarations using std::string_view are however possible.)

Doing this initialization in the header also has the benefit that every translation unit will automatically know the size of the array. Using extern and a definition in a single translation unit would mean that either other translation units don't know the size or that you have to manually enter the correct size in the declaration.

CodePudding user response:

I need to make global array of strings in file "misc.h".

You can use pointer to const char array. In this method, you don't need to use the extern keyword in the definition.

misc.h

//declaration-----v-------->note the pointer in this example
extern const char *str[];

misc.cpp

//definition, note no need for extern keyword here.
const char *str[] = {"some"," string"}; 

Working demo


Also What are the pros and cons in use of global variables? [closed]

  • Related