Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何避免;“多重定义”;全局常量的错误?_C_Winapi_Global Variables - Fatal编程技术网

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

我正在用WindowsAPI编写一个C程序。每个主要功能都有自己的文件,原型有一个头,包括和诸如此类的内容:

// 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[]=您可以将变量声明为
      static
      ,这样包含.h文件的每个模块都会获得自己的本地唯一副本,链接器不会对此抱怨,因为每个副本都有本地链接而不是外部链接。这也消除了将变量声明为
      extern
      并在单独的.c文件中定义它的需要

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

      或:


      您可以将变量声明为
      static
      ,这样包含.h文件的每个模块都会获得自己的本地唯一副本,链接器不会对此抱怨,因为每个副本都具有本地链接而不是外部链接。这也消除了将变量声明为
      extern
      并在单独的.c文件中定义它的需要

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

      或:


      头球后卫帮不了他
      #pragma once
      负责头部防护;这是一个链接器,而不是编译器,错误(请参阅我的答案)。标题保护不会帮助他
      #pragma once
      负责头部防护;这是一个链接器,而不是编译器,错误(请参阅我的答案)。
      #pragma once
      已经是一个头保护,所以这没有帮助。请看我的答案。
      #pragma once
      已经是一个标题保护,所以这不会有帮助。看我的答案。我认为这属于“除非你确定你知道你在做什么,否则不要尝试”的范畴。对我来说,让多个模块分别拥有一个声明过的变量的副本似乎不是一个好主意。我认为这属于“除非你确定你知道你在做什么,否则不要尝试”的范畴。对我来说,拥有多个模块,并分别复制一个声明过的变量似乎是个坏主意。