共享全局变量

如何创建在 C 中共享的全局变量?如果我把它放在一个头文件,然后链接器抱怨说,变量已经定义。在我的一个 C 文件中声明这个变量,并且在所有其他想要使用它的 C 文件的顶部手动放入 extern,这是唯一的方法吗?听起来不太理想。

219488 次浏览

In the header file write it with extern. And at the global scope of one of the c files declare it without extern.

In one header file (shared.h):

extern int this_is_global;

In every file that you want to use this global symbol, include header containing the extern declaration:

#include "shared.h"

To avoid multiple linker definitions, just one declaration of your global symbol must be present across your compilation units (e.g: shared.cpp) :

/* shared.cpp */
#include "shared.h"
int this_is_global;

You put the declaration in a header file, e.g.

 extern int my_global;

In one of your .c files you define it at global scope.

int my_global;

Every .c file that wants access to my_global includes the header file with the extern in.

In the header file

header file

#ifndef SHAREFILE_INCLUDED
#define SHAREFILE_INCLUDED
#ifdef  MAIN_FILE
int global;
#else
extern int global;
#endif
#endif

In the file with the file you want the global to live:

#define MAIN_FILE
#include "share.h"

In the other files that need the extern version:

#include "share.h"

If you're sharing code between C and C++, remember to add the following to the shared.hfile:

#ifdef __cplusplus
extern "C" {
#endif


extern int my_global;
/* other extern declarations ... */


#ifdef __cplusplus
}
#endif

There is a cleaner way with just one header file so it is simpler to maintain. In the header with the global variables prefix each declaration with a keyword (I use common) then in just one source file include it like this

#define common
#include "globals.h"
#undef common

and any other source files like this

#define common extern
#include "globals.h"
#undef common

Just make sure you don't initialise any of the variables in the globals.h file or the linker will still complain as an initialised variable is not treated as external even with the extern keyword. The global.h file looks similar to this

#pragma once
common int globala;
common int globalb;
etc.

seems to work for any type of declaration. Don't use the common keyword on #define of course.

There is a more elegant way to create global variables.

Just declare the variables as static inside a ".c" source file and create set/get functions.

The example below I use to override malloc, realloc and free functions during memory allocation tests.

Example:

memory-allocator.h

#ifndef MEMORY_ALLOCATOR_H_
#define MEMORY_ALLOCATOR_H_


#include <stddef.h>


void std_set_memory_allocators(void *(*malloc)(size_t size),
void *(realloc)(void *ptr, size_t size),
void (*free)(void *ptr));


void std_set_reset_allocators();


void *std_malloc(size_t size);


void *std_realloc(void *ptr, size_t size);


void std_free(void *ptr);


#endif  // MEMORY_ALLOCATOR_H_

memory-allocator.c

#include "memory-allocator.h"


#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>


typedef struct {
void *(*malloc)(size_t size);
void *(*realloc)(void *ptr, size_t size);
void (*free)(void *ptr);
} StdMemoryAllocator;


StdMemoryAllocator memory_allocators = {&malloc, &realloc, &free};


void std_set_memory_allocators(void *(*malloc)(size_t size),
void *(realloc)(void *ptr, size_t size),
void (*free)(void *ptr)) {
memory_allocators.malloc = malloc;
memory_allocators.realloc = realloc;
memory_allocators.free = free;
}


void std_set_reset_allocators() {
memory_allocators.malloc = malloc;
memory_allocators.realloc = realloc;
memory_allocators.free = free;
}


void *std_malloc(size_t size) {
return memory_allocators.malloc(size);
}


void *std_realloc(void *ptr, size_t size) {
return memory_allocators.realloc(ptr, size);
}


void std_free(void *ptr) {
memory_allocators.free(ptr);
}

The struct static struct StdMemoryAllocator_s memory_allocators is started automatically when the application starts, and it point to the default C memory allocators.