我有以下C++代码和运行PC的代码lint。
问题一:
#if !WIN32
#define ULONG_MAX 0xffffffff
#endif
上面的代码抛出一个lint错误,如下所示
错误26:应为表达式,找到"WIN32"
错误30:需要整数常量
如何修复上述错误?
问题二:
const char CompanyName[] = "mycompany";
错误:注解960:违反MISRA所需规则8.5,头文件中没有对象/函数定义
如何修复上述错误?
问题三:
unsigned long m_ClientThreadId;
m_ClientThreadId = 0;
注解960:违反MISRA所需规则10.1,隐式转换改变了符号性
如何修复上述错误?
6条答案
按热度按时间b5lpy0ml1#
您需要改为执行以下操作:
您不能在头文件中定义它,否则相同的符号将出现在多个编译单元中。
你需要做的只是在头中声明:
然后在其中一个模块中定义一次:
这是不寻常的,但是
0
似乎是一个有符号常量。并且将它赋值给unsigned long
会有一个隐式类型转换。大多数编译器实际上并不警告这种情况。yshpjwxd2#
有几点需要澄清,例如:
实际上,标准定义得很好,如果编译器调用总是包含
/DWIN32=1
或-DWIN32=0
,则可以合理地使用它。就此而言,标准规定,在宏扩展期间,未定义的符号将被0
替换,因此该行永远不会有任何问题,* 除非 * 某些其他约定规定该符号仅在Windows机器上定义,但是没有指定它被定义的值;在这种情况下,您需要类似以下内容:最后,这取决于您为处理编译器依赖项而建立的约定。
另一方面,应避免紧跟其后的行,因为它定义了C和C++标准中定义的符号(
ULONG_MAX
)。此处的三行序列应替换为:关于第二个问题,我不确定这个错误是否是对MISRA规则的错误解释,在C++中,
const
默认隐含内部链接:在头文件中定义这样的符号会导致变量的多个示例化(在每个翻译单元中有不同的地址),但不会导致多个定义的问题。2而且替代方法也有它们的缺点。3我的首选是用宏来代替变量定义:但是宏也有它们自己的问题。声明符号
extern
,然后在一个(且只有一个)源文件是另一种选择,但这涉及两个不同文件中的两条语句,其中(取决于变量所起的作用),一个可能更好。(从名字上看,我认为这两个声明不会是一个问题,但在其他情况下,最好保持文本在页眉中可见。)保持文本原样也是一种可行的选择,除非您的公司有严格的规定。关于最后一点,表达式
0
的类型为int
,它是有符号的,你可以明确指定类型0UL
,但坦率地说,这不是必须的:0
就是0
,与类型无关,虽然可能存在您想要强制该类型以确保算术以某种方式发生的情况,但这不是其中之一。至于错误/警告,我怀疑这也是对MISRA规则的误解;改变有符号性的隐式转换可能会有问题,但当被转换的是一个非常小的非负常量整数时就不会有问题。因此,如果需要遵守公司规则,请编写0UL
,但要意识到这是在把事情带到愚蠢的地步:一个基本上合理的规则被应用在不相关的情况下的例子。kqqjbcuj3#
对于第一个问题,我猜您应该使用
代替
因为WIN32宏并不总是存在的,你需要检查它的存在而不是它的“虚假”。
qfe3c7zg4#
对于第二个问题,那一行是在头文件中吗?一般来说,你不应该在头文件中 define 变量,特别是当头文件包含在多个文件中时,因为这会创建同一个变量的两个副本,并会导致链接错误。
6jygbczu5#
还有
#if !defined(WIN32)
,但#ifndef WIN32
更容易理解。nr9pn0ug6#
这些报告的错误都不是C++错误;是风格问题。
这是合法的。在
#if
指令中,任何未定义的标记都将被替换为0
。但正如其他人已经建议的那样,编写#ifndef WIN32
可能是更好的风格。但实际上,整个事情可能是一个坏主意。
ULONG_MAX
是在C标准头文件<limits.h>
和C++标准头文件<climits>
中定义的宏。合法,但不是个好主意。如果头文件是来自不同翻译单元的
#include
d,您将有CompanyName
的多个定义。(我不太清楚C++规则对此是怎么说的。)参见Mysticial的答案。这里PC-lint过于挑剔了。是的,
0
(类型为int
)到unsigned long
的隐式转换确实改变了有符号性,但在这种情况下,它不会导致任何可能的问题。但您可以使用unsigned long类型的文字来避免警告: