我正在使用 Windows API 编写 C 程序。每个主要功能都有自己的文件,并且有一个用于原型(prototype)和包含等等的标题:
// Headers & global constants
#pragma once
#define _WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WindowsX.h>
#include <Windef.h>
#define szClassName TEXT("EthicsPresentationWnd")
// Prototypes
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK FontProc1(HWND hWnd, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
ATOM RegisterWindow(HINSTANCE hInstance);
令我恼火的是 #define szClassName
行。我不喜欢使用宏,更愿意有一个合适的全局变量,wchar_t szClassName[]
,但如果我这样做,链接器会提示在包含头文件的每个模块中定义了多个变量。
我以为 #pragma once
指令会阻止这种情况,但事实并非如此。
这个问题有什么解决办法吗?
最佳答案
解决这个问题的方法是有一个单独的声明和定义......
header (*.h;抱歉,我不知道 WinAPI 类型名称,请根据需要进行调整):
extern const char szClassName[];
实现(*.c 或 *.cpp)
const char szClassName[] = "hello, world"
您看到问题是因为一个新符号 szClassName
每次您的 *.c 或 *.cpp 文件之一包含 header 时都会被声明(即使有包含保护!);这会让链接器感到困惑(见下文)。
请注意,这将使 sizeof(szClassName)
不再工作了。
进一步说明:
预处理后,编译器基本上是这样的:
- 文件“a.c”:
const char someSymbol[] = <some text, don't care what right now>;
- 文件“b.c”:
const char someSymbol[] = <some text, don't care if it's the same>;
- 文件“抄送”:
const char someSymbol[] = <some text, ditto>;
当链接器链接目标文件(例如,“a.obj”、“b.obj”和“c.obj”)时,它会看到用新值定义的相同符号(至少到链接器有关) --- 因此失败并出现错误。
关于c - 如何避免全局常量的 "multiple definition"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24717066/