c++ 应为表达式错误,找到“WIN32”

xa9qqrwz  于 2023-03-05  发布在  其他
关注(0)|答案(6)|浏览(134)

我有以下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,隐式转换改变了符号性
如何修复上述错误?

b5lpy0ml

b5lpy0ml1#

    • 第一名:**

您需要改为执行以下操作:

#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会有一个隐式类型转换。大多数编译器实际上并不警告这种情况。

yshpjwxd

yshpjwxd2#

有几点需要澄清,例如:

#if !WIN32

实际上,标准定义得很好,如果编译器调用总是包含/DWIN32=1-DWIN32=0,则可以合理地使用它。就此而言,标准规定,在宏扩展期间,未定义的符号将被0替换,因此该行永远不会有任何问题,* 除非 * 某些其他约定规定该符号仅在Windows机器上定义,但是没有指定它被定义的值;在这种情况下,您需要类似以下内容:

#ifndef WIN32

最后,这取决于您为处理编译器依赖项而建立的约定。
另一方面,应避免紧跟其后的行,因为它定义了C和C++标准中定义的符号(ULONG_MAX)。此处的三行序列应替换为:

#include <limits.h>

关于第二个问题,我不确定这个错误是否是对MISRA规则的错误解释,在C++中,const默认隐含内部链接:在头文件中定义这样的符号会导致变量的多个示例化(在每个翻译单元中有不同的地址),但不会导致多个定义的问题。2而且替代方法也有它们的缺点。3我的首选是用宏来代替变量定义:

#define CompanyName "mycompany"

但是宏也有它们自己的问题。声明符号extern,然后在一个(且只有一个)源文件是另一种选择,但这涉及两个不同文件中的两条语句,其中(取决于变量所起的作用),一个可能更好。(从名字上看,我认为这两个声明不会是一个问题,但在其他情况下,最好保持文本在页眉中可见。)保持文本原样也是一种可行的选择,除非您的公司有严格的规定。
关于最后一点,表达式0的类型为int,它是有符号的,你可以明确指定类型0UL,但坦率地说,这不是必须的:0就是0,与类型无关,虽然可能存在您想要强制该类型以确保算术以某种方式发生的情况,但这不是其中之一。至于错误/警告,我怀疑这也是对MISRA规则的误解;改变有符号性的隐式转换可能会有问题,但当被转换的是一个非常小的非负常量整数时就不会有问题。因此,如果需要遵守公司规则,请编写0UL,但要意识到这是在把事情带到愚蠢的地步:一个基本上合理的规则被应用在不相关的情况下的例子。

kqqjbcuj

kqqjbcuj3#

对于第一个问题,我猜您应该使用

#ifndef WIN32

代替

#if !WIN32

因为WIN32宏并不总是存在的,你需要检查它的存在而不是它的“虚假”。

qfe3c7zg

qfe3c7zg4#

对于第二个问题,那一行是在头文件中吗?一般来说,你不应该在头文件中 define 变量,特别是当头文件包含在多个文件中时,因为这会创建同一个变量的两个副本,并会导致链接错误。

6jygbczu

6jygbczu5#

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

nr9pn0ug

nr9pn0ug6#

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

    • 第一名:**
#if !WIN32
#define ULONG_MAX 0xffffffff
#endif

这是合法的。在#if指令中,任何未定义的标记都将被替换为0。但正如其他人已经建议的那样,编写#ifndef WIN32可能是更好的风格。
但实际上,整个事情可能是一个坏主意。ULONG_MAX是在C标准头文件<limits.h>和C++标准头文件<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;

相关问题