How to avoid “multiple definition” error for global constants?

自古美人都是妖i 提交于 2019-12-18 09:38:56

问题


I'm writing a C program using the Windows API. Each major function has its own file, and there is one header for the prototypes and includes and whatnot:

// 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);

The thing I'm irritated about is the #define szClassName line. I dislike using macros and would prefer to have a proper global variable, wchar_t szClassName[], but if I do that then the linker complains about multiply defined variables in each of the modules that include the header.

I thought the #pragma once directive would prevent this, but it didn't.

Is there any solution to this problem?


回答1:


The solution to this is to have a separate declaration and definition...

Header (*.h; sorry, I don't know WinAPI type names, adapt as necessary):

extern const char szClassName[];

Implementation (*.c or *.cpp)

const char szClassName[] = "hello, world"

You're seeing the problem because a new symbol szClassName is being declared each time one of your *.c or *.cpp files includes the header (even with the include guards!); and that makes the linker confused (see below).

Do note that this will make sizeof(szClassName) not work anymore.

Further explanation:

After preprocessing, the compiler is basically seeing this:

  • file "a.c": const char someSymbol[] = <some text, don't care what right now>;
  • file "b.c": const char someSymbol[] = <some text, don't care if it's the same>;
  • file "c.c": const char someSymbol[] = <some text, ditto>;

When the linker is linking the object files (say, "a.obj", "b.obj" and "c.obj"), it sees the same symbol being defined with a new value (at least as far as the linker is concerned) --- and thus it fails with an error.




回答2:


Use header guards in all your header file and declare a global variable in .c file and declare extern to that global variable in a header file.

#indef HEADER_FILE_NAME_H
#define HEADER_FILE_NAME_H
extern wchar_t szClassName[];
#endif

In any one of your .c file define the global variable.

wchar_t szClassName[];



回答3:


Place it in between

#ifndef GLOB_CONST_H
#define GLOB_CONST_H 

// All macro definitions
// and type definitions

#endif   

Use extern keyword to declare your global variables and put those declarations in this header file. After that you need to place the definition of all the variables in a .c file.




回答4:


You can declare the variable as static so that each module that includes the .h file gets its own local unique copy that the linker will not complain about, as each copy will have local linkage instead of external linkage. This also eliminates the need for declaring the variable as extern and defining it in a separate .c file.

static const TCHAR szClassName[] = TEXT("EthicsPresentationWnd");

Or;

static const TCHAR *szClassName = TEXT("EthicsPresentationWnd");

Or:

static LPCTSTR szClassName = TEXT("EthicsPresentationWnd");


来源:https://stackoverflow.com/questions/24717066/how-to-avoid-multiple-definition-error-for-global-constants

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!