奇怪的warning: “

tech2023-11-26  92

奇怪的warning: “__have_long64” is not defined

引子

最近在使用一款nb模块的opencpu来做项目,遇到了个奇怪的问题。

可能有的同学没接触过opencpu,待我简单介绍下。opencpu是用来替代传统cpu的。传统的物联网项目,用的是单片机+通信模块。而通信模块里面也是有处理器的,并且其资源(cpu算力,ram和flash)往往富余。既然如此,就有厂家把通信模块的cpu资源开放出来,给用户跑业务程序。这样省去了两个cpu的通信,也省去了单片机的成本,省力又省钱。

我用的nb软硬件环境如下: 处理器:mips系列 编译器:mips-elf-4.4.2,gcc系列

厂家的SDK很少使用标准库,使用的基本数据类型都是自己定义的。

/**************************************************************************** * Type Definitions ***************************************************************************/ typedef unsigned char bool; typedef unsigned char u8; typedef signed char s8; typedef unsigned short u16; typedef short s16; typedef unsigned int u32; typedef int s32; typedef unsigned long long u64; typedef long long s64; typedef unsigned int ticks;

我不太喜欢这种做法,大家都是用C语言,标准库明明有现成的类型,为啥不去用呢。如果都用标准的定义,那会便于移植第三方代码。

问题

当然,SDK用自己的类型,不妨碍我用标准库嘛。当我引入<stdint.h>时,遇到了一个神奇的问题。编译时报如下warning,说__have_long64和__int_fast64_t_defined未定义。

E:\CSDTK4\/mips-elf-4.4.2/mips-elf/sys-include/stdint.h:114:5: warning: "__have_long64" is not defined E:\CSDTK4\/mips-elf-4.4.2/mips-elf/sys-include/stdint.h:211:6: warning: "__int_fast64_t_defined" is not defined E:\CSDTK4\/mips-elf-4.4.2/mips-elf/sys-include/stdint.h:311:5: warning: "__have_long64" is not defined E:\CSDTK4\/mips-elf-4.4.2/mips-elf/sys-include/stdint.h:323:5: warning: "__have_long64" is not defined

先看看第一条warning指向的代码内容,即stdint.h文件114行。

stdint.h:144

#if __have_long64 typedef signed long int64_t; typedef unsigned long uint64_t; #define __int64_t_defined 1 #elif __have_longlong64 typedef signed long long int64_t; typedef unsigned long long uint64_t; #define __int64_t_defined 1 #elif __STDINT_EXP(INT_MAX) > 0x7fffffff typedef signed int int64_t; typedef unsigned int uint64_t; #define __int64_t_defined 1 #endif

如上代码是根据一些宏来决定int64_t和uint64_t是真64位,还是32位(假64)。#if命令在访问__have_long64时该标识符不存在,从而引发了warning。那么该变量是在哪儿定义的呢,还是就没有定义呢。

这个opencpu只提供了makefile编译系统,木有IDE。虽然我用了TRUEStudio来编辑代码,不过无法在IDE中查看mips的标准库。让我们用强大的grep来查下,

Administrator@XOCQELJM3TW78G3 MINGW64 /e/CSDTK4/mips-elf-4.4.2/mips-elf/sys-include $ grep -n --color -E "#define[[:space:]]+(\w+[[:space:]]+)*__have_long64" -R stdint.h:35:#define __have_long64 1

这不是定义了吗,看看该处的代码。 stdint.h:33

/* Check if "long" is 64bit or 32bit wide */ #if __STDINT_EXP(LONG_MAX) > 0x7fffffff #define __have_long64 1 #elif __STDINT_EXP(LONG_MAX) == 0x7fffffff && !defined(__SPU__) #define __have_long32 1 #endif

看来其是否定义是由LONG_MAX控制的。省去无聊的验证过程,最终确认: 定义了__have_long32和__have_longlong64,这样uint64_t是真的64位。确实没定义__have_long64。

这些宏开关为非0值时,会包含相应的定义。比如__have_longlong64用于定义真64位。

#elif __have_longlong64 typedef signed long long int64_t; typedef unsigned long long uint64_t; #define __int64_t_defined 1

解决

在不影响功能的情况下,想规避这个warning,我可以在头文件中添加:

#define __have_long64 0

加入后,__have_long64的warning是什么了,不过还有另一条。

I:\embedded\workspace\opencpu_nb_gas>make new - Building build/gcc/obj/custom/main.o In file included from common/_stddef.h:16, from common/rtthread.h:16, from utils/logger.h:6, from custom/main.c:40: E:\CSDTK4\/mips-elf-4.4.2/mips-elf/sys-include/stdint.h:212:6: warning: "__int_fast64_t_defined" is not defined

让我们再看看__int_fast64_t_defined吧。

推翻

等等,就这么把标准库的头文件给改了?这不大好吧,人家是标准库呢:)。

我们再来整理下问题:在#if命令中遇到了未定义的标识符,导致输出warning。

最简化模型为:

#if XXX #endif

随手找个编译器试了下(TRUEStudio创建的PC平台工程): 没有报warning。而且,mips编译器也只是报了warning,还是可以编译运行的。__have_long64被当成0来处理了。也就是说,这个warning可能是由编译参数来控制的,可以报警也可以不报警。毕竟,#if把未定义的标识符当成0,这看起来也很合理。

让我们看下TRUEStudio编译用的命令,只有与Warning相关的是-Wall。

gcc -O0 -g3 -Wall -c -fmessage-length=0 -std=gnu99 -o src\main.o ..\src\main.c

再看看NB SDK的编译命令,这个比较复杂,编译的部分参数如下:

CFLAGS=-std=gnu99 -mips16 -Wshadow -Os -g -msoft-float -Wundef -Wunused-function -Wuninitialized -minterlink-mips16 -nostdlib -nostdinc -nodefaultlibs -c \ -march=xcpu -mtune=xcpu -Wa,-march=xcpu,-mtune=xcpu \ -fno-inline-small-functions -fno-inline-functions -fno-align-functions -fno-align-jumps -fno-align-loops -fno-align-labels \ -pipe -fwide-exec-charset=UTF-16LE -fshort-wchar \ -fno-strict-aliasing -ffunction-sections -fdata-sections -fno-builtin-iswspace \ -ffixed-t3 -ffixed-t4 -ffixed-t5 -ffixed-t6 -ffixed-t7 -ffixed-s2 -ffixed-s3 -ffixed-s4 -ffixed-s5 -ffixed-s6 -ffixed-s7 -ffixed-fp -G0 -Wall \ -mexplicit-relocs -fweb -frename-registers -mmemcpy -mmips-tfile -nostartfiles \ -EL

再解决

万恶的-Wundef藏匿其中,不过逃不过我火眼金睛。gcc手册中–Wall和-Wundef的部分说明如下:

-Wall This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid. Note that some warning flags are not implied by ‘-Wall’. Some of them warn about constructions that users generally do not consider questionable, but which occasionally you might wish to check for; others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to modify the code to suppress the warning.-Wundef Warn if an undefined identifier is evaluated in an #if directive. Such identifiers are replaced with zero.

-Wall使能的warning有这么些特点:有些用户认为是可疑的(可能是bug),很容易规避。比如说,将int型变量赋值给指针。

int i = 0x08000000; int *p = i;

当然,如果int型变量确实存的就是另一个变量的地址,那么规避这个warning也很简单。

int *p = (int *)i;

-Wall的说明中也提到,其没有包含所有的warning。有些warning往往没有问题,不是潜在的bug。我觉得,-Wundef就是这种类型的。

stdint.h:144

#if __have_long64 typedef signed long int64_t; typedef unsigned long uint64_t; #define __int64_t_defined 1 #elif __have_longlong64 typedef signed long long int64_t; typedef unsigned long long uint64_t; #define __int64_t_defined 1 #elif __STDINT_EXP(INT_MAX) > 0x7fffffff typedef signed int int64_t; typedef unsigned int uint64_t; #define __int64_t_defined 1 #endif

再来回顾下这个__have_long64,#if在判断是否有long64时,其值为非0表示有。那么,定义一个值为0的__have_long64和不定义是一样的效果,挺合理的嘛。而且,像TRUEStudio这种IDE创建的工程,其默认的warning参数也只有-Wall,并没有-Wundef。修改个工程配置总比修改标准库文件要靠谱。

总结

#if遇到未定义的标识符时,会用0替换它。并且若编译参数加了-Wundef,则会输出warning。-Wall未包含-Wundef,可能开发者认为-Wundef不是一个可疑的warning,通常不需要关注。至于是否需要启用这条warning,就见仁见智了。

最后提一句:),NB SDK启用了-Wundef,其实并不是他们的开发者多么严谨。这SDK包含了部分开源代码和一套示例。我编译时,有100+的warning。边改边骂,那些warning可真是that are easy to avoid。虽然那些warning没有一个是真正的bug,但是我若不改的话,当我自己开发时触发了可疑的warning时,我的warning将被淹没中100+warning的大海之中。当然,如果那样的话,我也不会看到这条“__have_long64” is not defined。

转载请注明出处:https://blog.csdn.net/wenbodong/article/details/108387085 未经允许请勿用于商业用途。

最新回复(0)