C 如何避免;“多重定义”;全局常量的错误?
我正在用WindowsAPI编写一个C程序。每个主要功能都有自己的文件,原型有一个头,包括和诸如此类的内容:C 如何避免;“多重定义”;全局常量的错误?,c,winapi,global-variables,C,Winapi,Global Variables,我正在用WindowsAPI编写一个C程序。每个主要功能都有自己的文件,原型有一个头,包括和诸如此类的内容: // Headers & global constants #pragma once #define _WIN32_LEAN_AND_MEAN #include <Windows.h> #include <WindowsX.h> #include <Windef.h> #define szClassName TEXT("EthicsPrese
// 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);
//头和全局常量
#布拉格语一次
#定义\u WIN32 \u精益\u和\u平均值
#包括
#包括
#包括
#定义szClassName文本(“EthicsPresentationWnd”)
//原型
LRESULT回调WindowProc(HWND HWND,UINT Msg,WPARAM WPARAM,LPARAM LPARAM);
BOOL回调FontProc1(HWND-HWND,LPARAM-LPARAM);
int APIENTRY WinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、LPSTR lpCmdLine、int nShowCmd);
原子寄存器窗口(HINSTANCE-HINSTANCE);
我最恼火的是#define szClassName
行。我不喜欢使用宏,希望有一个合适的全局变量,wchar_t szClassName[]
,但如果我这样做了,链接器会抱怨在包含头的每个模块中都有多个定义的变量
我原以为#pragma once
指令会阻止这种情况发生,但事实并非如此
这个问题有什么解决办法吗?把它放在两者之间
#ifndef GLOB_CONST_H
#define GLOB_CONST_H
// All macro definitions
// and type definitions
#endif
使用extern
关键字声明全局变量,并将这些声明放在此头文件中。之后,您需要将所有变量的定义放在.c
文件中。将其放在两者之间
#ifndef GLOB_CONST_H
#define GLOB_CONST_H
// All macro definitions
// and type definitions
#endif
使用
extern
关键字声明全局变量,并将这些声明放在此头文件中。之后,您需要将所有变量的定义放在.c
文件中。在所有头文件中使用头保护,在.c文件中声明一个全局变量,并在头文件中声明该全局变量的extern
#ifndef HEADER_FILE_NAME_H /* if not defined already */
#define HEADER_FILE_NAME_H
extern wchar_t szClassName[];
#endif
在任何一个.c文件中定义全局变量
wchar_t szClassName[];
在所有头文件中使用头保护,在.c文件中声明一个全局变量,并在头文件中声明该全局变量的extern
#ifndef HEADER_FILE_NAME_H /* if not defined already */
#define HEADER_FILE_NAME_H
extern wchar_t szClassName[];
#endif
在任何一个.c文件中定义全局变量
wchar_t szClassName[];
解决这个问题的办法是有一个单独的声明和定义 标题(*.h;抱歉,我不知道WinAPI类型名称,请根据需要进行调整): 实施(*.c或*.cpp) 您看到这个问题是因为每当*.c或*.cpp文件中的一个包含头文件时(即使包含了include-guard!)都会声明一个新符号
szClassName
;这使得链接器很混乱(见下文)
请注意,这将使sizeof(szClassName)
不再工作
进一步解释:
预处理后,编译器基本上看到了以下情况:
- 文件“a.c”:
const char someSymbol[]=解决方案是使用单独的声明和定义 标题(*.h;抱歉,我不知道WinAPI类型名称,请根据需要进行调整): 实施(*.c或*.cpp) 您看到这个问题是因为每当*.c或*.cpp文件中的一个包含头文件时(即使包含了include-guard!)都会声明一个新符号
;这使得链接器很混乱(见下文) 请注意,这将使szClassName
不再工作 进一步解释: 预处理后,编译器基本上看到了以下情况:sizeof(szClassName)
- 文件“a.c”:
const char someSymbol[]=您可以将变量声明为
,这样包含.h文件的每个模块都会获得自己的本地唯一副本,链接器不会对此抱怨,因为每个副本都有本地链接而不是外部链接。这也消除了将变量声明为static
并在单独的.c文件中定义它的需要extern
或 或:static const TCHAR szClassName[] = TEXT("EthicsPresentationWnd");
您可以将变量声明为
,这样包含.h文件的每个模块都会获得自己的本地唯一副本,链接器不会对此抱怨,因为每个副本都具有本地链接而不是外部链接。这也消除了将变量声明为static
并在单独的.c文件中定义它的需要extern
或 或:static const TCHAR szClassName[] = TEXT("EthicsPresentationWnd");
头球后卫帮不了他
负责头部防护;这是一个链接器,而不是编译器,错误(请参阅我的答案)。标题保护不会帮助他#pragma once
负责头部防护;这是一个链接器,而不是编译器,错误(请参阅我的答案)。#pragma once
已经是一个头保护,所以这没有帮助。请看我的答案。#pragma once
已经是一个标题保护,所以这不会有帮助。看我的答案。我认为这属于“除非你确定你知道你在做什么,否则不要尝试”的范畴。对我来说,让多个模块分别拥有一个声明过的变量的副本似乎不是一个好主意。我认为这属于“除非你确定你知道你在做什么,否则不要尝试”的范畴。对我来说,拥有多个模块,并分别复制一个声明过的变量似乎是个坏主意。#pragma once
- 文件“a.c”: