1

我有以下 C++ 代码并在代码上运行 PC lint。

问题一:

#if !WIN32
#define ULONG_MAX 0xffffffff
#endif

上面的代码抛出一个 lint 错误,如下所示

错误 26:需要一个表达式,发现 'WIN32'
错误 30:需要一个整数常量

如何解决上述错误?

问题2:

const char CompanyName[] = "mycompany"; 

错误:注 960:违反 MISRA 要求的规则 8.5,头文件中没有对象/函数定义

如何解决上述错误?

问题 3:

unsigned long m_ClientThreadId; 
m_ClientThreadId        = 0;

注释 960:违反 MISRA 要求的规则 10.1,隐式转换更改签名

如何解决上述错误?

4

6 回答 6

4

第一的:

你需要这样做:

#ifndef WIN32
#define ULONG_MAX 0xffffffff
#endif

第二:

不能在头文件中定义,否则同一个符号会出现在多个编译单元中。

您需要做的只是在标题中声明:

extern const char CompanyName[];

然后在其中一个模块中定义一次:

const char CompanyName[] = "mycompany"; 

第三:

unsigned long m_ClientThreadId; 
m_ClientThreadId        = 0;

这是不寻常的,但它似乎0是一个有符号常数。并将其分配给unsigned long具有隐式类型转换。大多数编译器实际上并没有对此提出警告。

于 2011-11-10T08:15:10.853 回答
2

有几点需要澄清。例如,该行:

#if !WIN32

实际上由标准很好地定义,并且如果您的编译器调用总是包含 t/DWIN32=1-DWIN32=0. 就此而言,标准规定未定义的符号0在宏扩展期间被替换为它被定义为未指定;在这种情况下,您需要类似:

#ifndef WIN32

最后,它取决于您为处理编译器依赖项而建立的约定。

另一方面,应避免紧随其后的行,因为它定义了一个符号 ( ULONG_MAX),该符号在 C 和 C++ 标准中定义。这里的三行顺序应该替换为:

#include <limits.h>

关于第二个问题,我不确定该错误是否是对 MISRA 规则的错误解释。在 C++ 中,const默认情况下意味着内部链接:在标头中定义这样的符号将导致变量的多个实例化(每个翻译单元中具有不同的地址),但不会导致多个定义出现问题。替代方案也有其缺点。我的偏好是用宏替换变量定义:

#define CompanyName "mycompany"

但是宏也有自己的问题。声明符号extern,然后在一个(并且只有一个)源文件中定义它是另一种选择,但这涉及两个语句,在两个不同的文件中,其中(取决于变量所扮演的角色),一个可能更可取。(从名称来看,我认为这两个语句不会成为问题,但在其他情况下,最好将文本保持在标题中可见。)保持原样也是可行的替代方案,除非您的公司对此有严格的规定。

关于最后一点,表达式0的类型int是有符号的。您可以清楚地指定类型,0UL但坦率地说,这不是必需的:0is 0,无论类型如何,虽然可能存在您想要强制类型的情况,以确保以某种方式进行算术,这不是其中之一。至于错误/警告,我怀疑这也是对 MISRA 规则的误解;改变符号的隐式转换可能会出现问题,但当转换的是非常小的非负常数整数时则不会。所以写0UL如果您需要遵守公司规则,但要意识到这将事情带到了愚蠢的地步:在不相关的情况下应用基本合理的规则的情况。

于 2011-11-10T08:37:05.783 回答
1

For the first question, I'd guess the you should use

#ifndef WIN32

instead of

#if !WIN32

since the WIN32 macro not always exists, and you need to check for its existence rather than its "falseness".

于 2011-11-10T08:16:19.593 回答
0

For question number two, is that line inside a header file? You should in general never define variables in headers, especially if that header is included in more than one file as that will create two copies of the same variable and will result in a link error.

于 2011-11-10T08:15:52.207 回答
0

也有#if !defined(WIN32),但#ifndef WIN32更容易理解。

于 2011-11-10T08:30:26.837 回答
0

这些报告的错误都不是 C++ 错误;他们是风格问题。

第一的:

#if !WIN32
#define ULONG_MAX 0xffffffff
#endif

这是合法的。在#if指令中,任何未定义的标记都将替换为0. 但#ifndef WIN32正如其他人已经建议的那样,它可能是更好的写作风格。

但实际上,整个事情可能是个坏主意。 是在 C 标准头文件和 C++ 标准头文件ULONG_MAX中定义的宏。将以上 3 行替换为:<limits.h><climits>

#include <climits>

第二:

const char CompanyName[] = "mycompany";

合法,但一个坏主意。如果头文件是#include来自不同翻译单元的 d,您将有多个CompanyName. (我不太确定 C++ 规则对此有何规定。)请参阅 Mysticial 的回答。

第三:

unsigned long m_ClientThreadId; 
m_ClientThreadId        = 0;

在这里,PC-lint 过于挑剔了。0是的, (类型为int)的隐式转换unsigned long确实会改变签名,但在这种情况下,它不会导致任何可能的问题。但是您可以通过使用 unsigned long 类型的文字来避免警告:

unsigned long m_ClientThreadId; 
m_ClientThreadId        = 0UL;
于 2011-11-10T08:36:02.007 回答