我该如何创建在C中共享的全局变量?如果将其放在头文件中,则链接器会抱怨变量已经定义。难道唯一的方法是在我的一个C文件中声明变量,并在想使用它的所有其他C文件的顶部手动添加extern
吗?这听起来不太理想。
我该如何创建在C中共享的全局变量?如果将其放在头文件中,则链接器会抱怨变量已经定义。难道唯一的方法是在我的一个C文件中声明变量,并在想使用它的所有其他C文件的顶部手动添加extern
吗?这听起来不太理想。
在一个头文件中 (shared.h):
extern int this_is_global;
在每个想要使用这个全局符号的文件中,都需要包含包含extern声明的头文件:#include "shared.h"
为了避免多个链接器定义,你的全局符号只能在编译单元中存在一个声明(例如:shared.cpp):
/* shared.cpp */
#include "shared.h"
int this_is_global;
在头文件中使用 extern
关键字进行声明。
并且在某个 C 文件的全局作用域中不使用 extern
进行声明。
在头文件中
#ifndef SHAREFILE_INCLUDED
#define SHAREFILE_INCLUDED
#ifdef MAIN_FILE
int global;
#else
extern int global;
#endif
#endif
在你想要全局变量存在的文件中:
#define MAIN_FILE
#include "share.h"
在需要使用外部版本的其他文件中:
#include "share.h"
你将声明放在头文件中,例如:
extern int my_global;
在你的一个 .c 文件中,你在全局范围内定义了它。int my_global;
所有想要访问my_global
的.c文件都会包含带有extern
的头文件。
如果你在C和C++之间共享代码,请记得将以下内容添加到shared.h
文件中:
#ifdef __cplusplus
extern "C" {
#endif
extern int my_global;
/* other extern declarations ... */
#ifdef __cplusplus
}
#endif
有一种更简洁的方式,只需要一个头文件,因此更容易维护。 在全局变量的头文件中,每个声明都要以关键字(我使用common)为前缀,然后在一个源文件中这样包含它:
#define common
#include "globals.h"
#undef common
以及像这样的任何其他源文件
#define common extern
#include "globals.h"
#undef common
请确保不要在globals.h文件中初始化任何变量,否则链接器仍会抱怨,因为初始化的变量即使使用extern关键字也不会被视为外部变量。global.h文件类似于以下内容:
#pragma once
common int globala;
common int globalb;
etc.
这似乎适用于任何类型的声明。当然,不要在 #define 中使用常见的关键字。
#ifndef common
#define common extern
#endif
。唯一的注意点是common不会自动未定义。 - GDavid有一种更优雅的方法来创建全局变量。
只需在“.c”源文件中将变量声明为静态,并创建set/get函数即可。
下面的示例我用于在内存分配测试期间覆盖malloc,realloc和free函数。
示例:
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);
}
结构体 static struct StdMemoryAllocator_s memory_allocators
在应用程序启动时自动启动,并指向默认的 C 内存分配器。