代碼片段 1(如下所示)產生以下 -Wconversion 警告:
debug_Wconversion.c:10:57: warning: conversion to ‘uint16_t’ from ‘int’ may alter its value [-Wconversion]
result = ((uint16_t) (((uint16_t) byte1) & 0x0050)) | ((uint16_t) byte2);
^
代碼片段 2 和 3 不會產生 -Wconversion 警告。
代碼片段 1:
uint8_t byte1 = 0xF0;
uint8_t byte2 = 0x0F;
uint16_t result;
result = ((uint16_t) (((uint16_t) byte1) & 0x0050)) | ((uint16_t) byte2);
代碼片段 2:
uint8_t byte1 = 0xF0;
uint8_t byte2 = 0x0F;
uint16_t result;
uint16_t leftOrOperand;
uint16_t rightOrOperand;
leftOrOperand = ((uint16_t) (((uint16_t) byte1) & 0x0050));
rightOrOperand = ((uint16_t) byte2);
result = leftOrOperand | rightOrOperand;
代碼片段 3:
uint8_t byte1 = 0xF0;
uint8_t byte2 = 0x0F;
uint16_t result;
result = (uint16_t) (((uint16_t) (((uint16_t) byte1) & 0x0050)) | ((uint16_t) byte2));
為什么第一個代碼片段會產生警告,而其他代碼片段不會?導致警告的具體原因是什么?
我覺得這很令人困惑。盡管顯式轉換了運算元,但第一個片段中的警告暗示在按位或操作中發生了整數提升。第二個片段演示了按位或操作本身不會導致整數提升。如果保留操作順序,第三個代碼段執行與第一個代碼段相同的操作,但在分配結果變數之前轉換按位或的結果。很明顯,我無法理解強制轉換和按位或操作之間的相互作用。任何幫助澄清我的理解將不勝感激!
其他可能相關的資訊:
- gcc (GCC) 4.8.5 20150623(我無法升級,但這似乎也發生在較新的版本上)
- -std=c11
- -Wconversion 警告存在于默認優化(未提供設定)和禁用優化(-O0)
提前致謝!
uj5u.com熱心網友回復:
按位 OR 運算子|和按位 AND 運算子&都對兩個運算元執行整數提升。運算元之一是強制轉換的結果這一事實不會改變這一點。
該-Wconversion標志往往是關于什么警告就有點過于熱情。由于32位int,從轉換uint16_t到int會不會改變其值。
C 標準確實指定 an 的最小范圍int是 -32767 到 32767,因此具有此限制的實作可能會看到值更改,盡管您將很難找到運行 gcc 的系統在這種情況下.
然而,這個特殊的警告被演員壓制了。從手冊頁:
-W轉換
警告可能會改變值的隱式轉換。這包括實數和整數之間的轉換,如“abs (x)”,當“x”為“double”時;有符號和無符號之間的轉換,如“unsigned ui = -1”;并轉換為較小的型別,例如“sqrtf (M_PI)”。不要警告像 "abs ((int) x)" 和 "ui = (unsigned) -1" 這樣的顯式轉換,或者如果像 "abs (2.0)" 那樣的轉換沒有改變值。可以使用 -Wno-sign-conversion 禁用有關有符號和無符號整數之間轉換的警告。
對于 C ,還警告混淆用戶定義轉換的多載決議;和從不使用型別轉換運算子的轉換:轉換為“void”、相同型別、基類或對它們的參考。除非顯式啟用 -Wsign-conversion,否則 C 中默認禁用有關有符號和無符號整數之間轉換的警告。
uj5u.com熱心網友回復:
為什么第一個代碼片段會產生警告,而其他代碼片段不會?導致警告的具體原因是什么?
((uint16_t) (((uint16_t) byte1) & 0x0050)) | ((uint16_t) byte2)是一個int被分配給 a uint16_t。
((uint16_t) (((uint16_t) byte1) & 0x0050))是一個uint16_t。
((uint16_t) byte2)也是一個 uint16_t。
uint16_t | uint16_t首先推出的運算元int前|。
代碼正在將inta分配給 a uint16_t- 因此警告。
在第二個代碼段中,編譯器更好地理解 or'ing 兩個uint16_t(結果也是int)不會導致向下轉換為uint16_t. 第一個只是有點太復雜,編譯器無法推斷出任何問題。
在第三場比賽中,最后的演員陣容消除了任何向下轉換問題。
替代方法:使用一個unsigned常量:0x0050u和unsignedmath 用于無符號型別,如uint16_t.
uint8_t byte1 = 0xF0u;
uint8_t byte2 = 0x0Fu;
// v-------------v unsigned result
// v-----v unsigned constant
uint16_t result = (byte1 & 0x0050u) | byte2;
// ^-----------------------^ unsigned result
// ^--------------------------------^ initializing: unsigned to uint16_t
一個討厭的編譯器可能仍然抱怨縮小初始化。
// Non-cast alternative
uint16_t result = UINT16_MAX & ((byte1 & 0x0050u) | byte2);
// Cast alternative
uint16_t result = (uint16_t) ((byte1 & 0x0050u) | byte2);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/331928.html
上一篇:取消參考指標如何回傳垃圾值?
