[英]Expected an expression error
我有以下C ++代碼並在代碼上運行PC Lint。
問題1:
#if !WIN32
#define ULONG_MAX 0xffffffff
#endif
上面的代碼拋出一個皮棉錯誤,如下所示
錯誤26:預期為表達式,找到“ WIN32”
錯誤30:預期為整數常數
如何解決以上錯誤?
問題2:
const char CompanyName[] = "mycompany";
錯誤:注釋960:違反了MISRA要求的規則8.5,頭文件中沒有對象/函數定義
如何解決以上錯誤?
問題3:
unsigned long m_ClientThreadId;
m_ClientThreadId = 0;
注釋960:違反了MISRA要求的規則10.1,隱式轉換更改了簽名
如何解決以上錯誤?
第一:
您需要這樣做:
#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
具有隱式類型轉換。 大多數編譯器實際上並未對此提出警告。
有幾點需要澄清。 例如,該行:
#if !WIN32
由標准實際上很好地定義,並且如果編譯器調用始終包含/DWIN32=1
或-DWIN32=0
,則可以合理地使用它。 為此,該標准表示,宏擴展期間未定義的符號將替換為0
,因此該行永遠不會有任何問題, 除非某些其他約定指出該符號僅在Windows計算機上定義,但是未定義定義的值; 在這種情況下,您需要以下內容:
#ifndef WIN32
最后,它取決於您為處理編譯器依賴項而建立的約定。
另一方面,應避免緊隨其后的那一行,因為它定義了在C和C ++標准中定義的符號( ULONG_MAX
)。 這里的三行序列應替換為:
#include <limits.h>
關於第二個問題,我不確定該錯誤是否是對MISRA規則的誤解。 在C ++中,默認情況下const
表示內部鏈接:在標頭中定義這樣的符號將導致變量的多個實例化(每個轉換單元中的地址不同),但不會導致多個定義出現問題。 替代方案也有其缺點。 我的偏好是將變量定義替換為宏:
#define CompanyName "mycompany"
但是宏有其自身的問題。 聲明符號extern
,然后在一個(只有一個)源文件中對其進行定義是另一種選擇,但這涉及兩個語句,在兩個不同的文件中,其中(取決於變量所扮演的角色),一個語句可能更可取。 (從名稱來看,我認為這兩個語句不是問題,但在其他情況下,最好使標題中的文本保持可見。)將其保留在編寫時也是可行的除非您的公司有嚴格的規定禁止這樣做。
關於最后一點,表達式0
具有類型int
,該類型為有符號。 您可以清楚地指定類型0UL
,但坦率地說,不必指定: 0
是0
,而不管類型如何,並且在某些情況下您想強制使用該類型,以確保算術在a中進行。以某種方式,這不是其中之一。 至於錯誤/警告,我懷疑這也是對MISRA規則的誤解; 更改符號度的隱式轉換可能會出現問題,但當轉換的內容是非常小的非負常數整數時,則不會出現問題。 因此,如果您需要遵守公司規則,請寫0UL
,但一定要意識到這將事情帶到了愚蠢的地步:在不相關的情況下應用了基本合理的規則。
對於第一個問題,我猜您應該使用
#ifndef WIN32
代替
#if !WIN32
因為WIN32宏並不總是存在,所以您需要檢查它的存在而不是它的“錯誤”。
對於第二個問題,該行是否位於頭文件中? 通常,您永遠不要在標頭中定義變量,尤其是如果該標頭包含在多個文件中,因為這將創建同一變量的兩個副本並導致鏈接錯誤。
還有#if !defined(WIN32)
,但是#ifndef WIN32
更容易理解。
這些報告的錯誤都不是C ++錯誤。 他們是風格問題。
第一:
#if !WIN32
#define ULONG_MAX 0xffffffff
#endif
這是合法的。 在#if
指令中,所有未定義的令牌都將替換為0
。 但是編寫#ifndef WIN32
可能是更好的樣式,正如其他人已經建議的那樣。
但實際上,整個事情可能不是一個好主意。 ULONG_MAX
是在C標准標頭<limits.h>
和C ++標准標頭<climits>
定義的宏。 將以上3行替換為:
#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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.