2017-04-04 98 views
4

我的靜態分析器是投擲以下警告:MISRA C++規則5-0-3假陽性警告

MCPP規則5-0-3:該複合物的表達隱式轉換爲 不同必不可少類型

爲以下代碼:

void func(const uint32_t arg) 
{ 
    //32U has underlying type uint8_t 
    const uint32_t u32a = arg % 32U; //warning issued in this line 
    const uint32_t u32b = (arg % static_cast<uint32_t>(32U)); //same warning issued in this line 
    const uint32_t u32c = static_cast<uint32_t>(arg % 32U); //compliant 
} 

根據MISRA底層類型轉換規則:

否則,如果兩個運算數均爲整數類型,基礎類型的 的表達可以使用以下發現:

- 如果類型 操作數具有相同的尺寸,並且或者是無符號的,結果是 未簽名。

- 否則,結果的類型是較大的 類型。

我認爲這種警告可能是假陽性,因爲,儘管32U是一個uint8_t,表達式應該採取的基礎類型的較大型的,在這種情況下,uint32_t,從而使爲static_cast不必要的需要。

您是否同意這是一個誤報?或者我看着這一切都錯了?

編輯: 的MISRA標準指出:

基礎類型的整數常量表達式的因此是 定義如下:

  1. 如果表達式的實際類型是有符號的積分,底層類型被定義爲 能夠表示其值的最小有符號整數類型。

  2. 如果表達式的實際類型是無符號整數,基礎類型被定義爲最小無符號整數類型 是能夠代表其值的。

  3. 在所有其他情況下,表達式的基礎類型被定義爲與其實際類型相同。

2號就是爲什麼我一直假設32U具有基礎類型的uint8_t的原因。

+0

在你的架構,'32U'可能是64位。你爲什麼說「_32U有基礎類型uint8_t_」? – YSC

+1

如果你的int是比'uint32_t'越大,則'ARG%32U'是類型'無符號int'而不是'uint32_t'的。 – Jarod42

+0

要檢查,只是'的std ::法院<<的sizeof(unsigned int類型)<< 「\ n」;'。 – YSC

回答

1

您已找到相關部分。文字所在表達式的類型是無符號的,所以基礎類型是可以適合無符號值32,即uint8_t的最小的一個。如果沒有U後綴的文字是32(儘管這會違反其他MISRA規則),它將具有相同的基礎類型。

MISRA的目標是在特定表達式uint32_t arg; ... arg % 32U中永遠不會發生危險的隱式轉換。話雖如此,你可以安全地將文字轉換成uint32_t,並且應該使所有警告消失。無論MISRA說/不說什麼,確保代碼中不存在隱式類型促銷活動,這是很好的編程實踐。

如果靜態分析器的目的通常是檢查隱式升級,那麼警告就沒有問題。如果您的靜態分析儀的目的是檢查MISRA合規性,那麼這是一個誤報。

arg % static_cast<uint32_t>(32U)從不應該產生任何形式的診斷,而不管該工具的目的。這當然是一個誤報。

2

我認爲這個警告可能是假陽性,因爲,儘管32U是一個uint8_t

32U沒有任何平臺上uint8_t。對於整數文字,您可以表達的最小類型是int/unsigned intAccording to cppreferencennnnU可以是 a unsigned int,unsigned long intunsigned long long int。它確實選擇了第一種可存儲文字的類型,所以32Uunsigned int

所以,如果你想保證32U是與uint32_t相同的類型,那麼你需要在右側的演員陣容。

+0

我剛剛修改後 – mikearmagedon

+0

@mikearmagedon我不熟悉MISRA這樣我就可以知道B一定的,但我認爲在談論剛剛'32'。正如你在編譯時所知道的那樣,'32'可以被視爲一個有效的'uint8_t'。用32U,儘管你告訴編譯器你希望它是一個帶'U'的'unsigned int'。 – NathanOliver

+0

@NathanOliver。字面值'32'是'int'類型。 – Peter

2

32Uunsigned類型,它可能是與uint32_t不同的類型。相反,你的說法,它的類型是uint8_t

一個unsigned的永遠只保證能夠在範圍0代表值65535,雖然它允許支持更大的範圍。它實際上可以表示的是實現定義的。但是,它不能是uint8_t,因爲uint8_t不能表示unsigned所需的範圍。

這意味着,實際上有三種可能性,即unsigned可能是16位類型,32位類型甚至是64位類型 - 並且它們分別更小,相同尺寸或​​更大比uint32_t

的表達式的結果因此arg % 32U可以是uint32_t型的(如果unsigned是16位),uint32_t(如果unsigneduint32_t都是相同的32位類型),或unsigned(如果unsigned是一個64位類型)。在最後一種情況下,需要將unsigned轉換爲uint32_t以初始化u32a

您的靜態分析器警告您系統之間行爲的這種潛在變化。

所以,不,這不是假陽性。

+0

的問題是關於MISRA-C++ 2008的基礎類型的概念,所以這並不能回答這個問題。 – Lundin