如何在c中进行全局定义?为什么 #pragma once 或 include guard 不起作用?
How to make global definitions in c? Why #pragma once or include guard not working?
我正在使用 EFM32 PG12 入门套件和 Simplicity Studio 进行显微镜的微控制器项目。在这个项目中,我在 .h 文件中做了一些全局引脚和端口定义 global_definitions.h
因为复杂所以才这样做。不同文件中的许多函数直接访问引脚、思想定时器或通过 PRS。
这里是一些global_definitions.h:
#pragma once //not working
#define startUpMessage "I:000:Initialization finished"
#define prsChannel 6
//pin definitions for the lasers
unsigned int laserPinNumbers[]={2,3,12,13,14,15};
unsigned int laserPorts[]={gpioPortA,gpioPortA,gpioPortD,gpioPortD,gpioPortD,gpioPortD};
unsigned int laserTimers[]={0,0,1,1,1,1};
#define timer0 WTIMER0
#define timer1 WTIMER1
等等...
如果我尝试编译我的项目,我会收到错误消息:
arm-none-eabi-gcc -g3 -gdwarf-2 -mcpu=cortex-m4 -mthumb -T "SLM_PG12_3.ld" -Xlinker --gc-sections -Xlinker -Map="SLM_PG12_3.map" -mfpu=fpv4-sp-d16 -mfloat-abi=softfp --specs=nano.specs -o SLM_PG12_3.axf "./CMSIS/EFM32PG12B/startup_efm32pg12b.o" "./CMSIS/EFM32PG12B/system_efm32pg12b.o" "./emlib/em_cmu.o" "./emlib/em_core.o" "./emlib/em_gpio.o" "./emlib/em_prs.o" "./emlib/em_rtc.o" "./emlib/em_rtcc.o" "./emlib/em_system.o" "./emlib/em_timer.o" "./emlib/em_usart.o" "./emlib/udelay.o" "./src/i2c.o" "./src/izi_usart.o" "./src/laserSequences.o" "./src/leds.o" "./src/main.o" -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
./src/leds.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:12: multiple definition of `laserPinNumbers'
./src/laserSequences.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:12: first defined here
./src/leds.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:13: multiple definition of `laserPorts'
./src/laserSequences.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:13: first defined here
...
collect2: error: ld returned 1 exit status
make: *** [SLM_PG12_3.axf] Error 1
包括守卫
#ifndef GLOBAL_DEFINITIONS
#define GLOBAL_DEFINITIONS
...
#endif
也不工作。
在 c 中进行全局定义的正确方法是什么?
谢谢。
#pragma once
在编译 单个 源文件时保护头文件免受多重包含。因此,如果您编译 leds.c
并尝试多次包含此文件,可能来自不同包含级别的其他包含文件,pragma 保证该文件在此编译期间仅解析一次。编译 laserSequences.c
时也会发生同样的情况。
现在您已经编译了至少 2 个 .o
形式的源文件。每个人都包含一次头文件,每个人都从这个头文件中声明全局变量。链接器抱怨,因为它不知道使用哪一个。
解决方法是从不在头文件中声明变量。您只需提供其外部链接的定义。声明必须在一个且仅一个源文件中完成,例如:
global_definitions.h:
#pragma once
#define startUpMessage "I:000:Initialization finished"
#define prsChannel 6
extern unsigned int laserPinNumbers[];
extern unsigned int laserPorts[];
extern unsigned int laserTimers[];
...
现在在 一个 的 .c
文件中,无论是在您已有的文件中还是在其他文件中,例如,global_definitions.c
您都可以声明变量:
unsigned int laserPinNumbers[]={2,3,12,13,14,15};
unsigned int laserPorts[]={gpioPortA,gpioPortA,gpioPortD,gpioPortD,gpioPortD,gpioPortD};
unsigned int laserTimers[]={0,0,1,1,1,1};
此外,#pragma once
是一个相对较新的标准(它可能不适用于旧版本的编译器),它取代了保护宏。它们的工作方式相同。
我正在使用 EFM32 PG12 入门套件和 Simplicity Studio 进行显微镜的微控制器项目。在这个项目中,我在 .h 文件中做了一些全局引脚和端口定义 global_definitions.h
因为复杂所以才这样做。不同文件中的许多函数直接访问引脚、思想定时器或通过 PRS。
这里是一些global_definitions.h:
#pragma once //not working
#define startUpMessage "I:000:Initialization finished"
#define prsChannel 6
//pin definitions for the lasers
unsigned int laserPinNumbers[]={2,3,12,13,14,15};
unsigned int laserPorts[]={gpioPortA,gpioPortA,gpioPortD,gpioPortD,gpioPortD,gpioPortD};
unsigned int laserTimers[]={0,0,1,1,1,1};
#define timer0 WTIMER0
#define timer1 WTIMER1
等等...
如果我尝试编译我的项目,我会收到错误消息:
arm-none-eabi-gcc -g3 -gdwarf-2 -mcpu=cortex-m4 -mthumb -T "SLM_PG12_3.ld" -Xlinker --gc-sections -Xlinker -Map="SLM_PG12_3.map" -mfpu=fpv4-sp-d16 -mfloat-abi=softfp --specs=nano.specs -o SLM_PG12_3.axf "./CMSIS/EFM32PG12B/startup_efm32pg12b.o" "./CMSIS/EFM32PG12B/system_efm32pg12b.o" "./emlib/em_cmu.o" "./emlib/em_core.o" "./emlib/em_gpio.o" "./emlib/em_prs.o" "./emlib/em_rtc.o" "./emlib/em_rtcc.o" "./emlib/em_system.o" "./emlib/em_timer.o" "./emlib/em_usart.o" "./emlib/udelay.o" "./src/i2c.o" "./src/izi_usart.o" "./src/laserSequences.o" "./src/leds.o" "./src/main.o" -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
./src/leds.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:12: multiple definition of `laserPinNumbers'
./src/laserSequences.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:12: first defined here
./src/leds.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:13: multiple definition of `laserPorts'
./src/laserSequences.o:/home/grafmakula/SimplicityStudio/v4_workspace/SLM_PG12_3/GNU ARM v7.2.1 - Debug/../src/global_definitions.h:13: first defined here
...
collect2: error: ld returned 1 exit status
make: *** [SLM_PG12_3.axf] Error 1
包括守卫
#ifndef GLOBAL_DEFINITIONS
#define GLOBAL_DEFINITIONS
...
#endif
也不工作。
在 c 中进行全局定义的正确方法是什么?
谢谢。
#pragma once
在编译 单个 源文件时保护头文件免受多重包含。因此,如果您编译 leds.c
并尝试多次包含此文件,可能来自不同包含级别的其他包含文件,pragma 保证该文件在此编译期间仅解析一次。编译 laserSequences.c
时也会发生同样的情况。
现在您已经编译了至少 2 个 .o
形式的源文件。每个人都包含一次头文件,每个人都从这个头文件中声明全局变量。链接器抱怨,因为它不知道使用哪一个。
解决方法是从不在头文件中声明变量。您只需提供其外部链接的定义。声明必须在一个且仅一个源文件中完成,例如:
global_definitions.h:
#pragma once
#define startUpMessage "I:000:Initialization finished"
#define prsChannel 6
extern unsigned int laserPinNumbers[];
extern unsigned int laserPorts[];
extern unsigned int laserTimers[];
...
现在在 一个 的 .c
文件中,无论是在您已有的文件中还是在其他文件中,例如,global_definitions.c
您都可以声明变量:
unsigned int laserPinNumbers[]={2,3,12,13,14,15};
unsigned int laserPorts[]={gpioPortA,gpioPortA,gpioPortD,gpioPortD,gpioPortD,gpioPortD};
unsigned int laserTimers[]={0,0,1,1,1,1};
此外,#pragma once
是一个相对较新的标准(它可能不适用于旧版本的编译器),它取代了保护宏。它们的工作方式相同。