[英]What is the difference between using INTXX_C macros and performing type cast to literals?
例如,這段代碼被破壞了(我剛剛在實際代碼中修復了它......)。
uint64_t a = 1 << 60
它可以固定為,
uint64_t a = (uint64_t)1 << 60
但后來這通過了我的大腦。
uint64_t a = UINT64_C(1) << 60
我知道UINT64_C(1)
是一個在 64 位系統中通常擴展為1ul
的宏,但是它與僅僅進行類型轉換有什么不同呢?
(uint64_t)1
形式上是轉換為uint64_t
的int
值1
1ul
是unsigned long
類型的常量1
,它可能與 64 位系統上的uint64_t
相同。
宏是為uint64_t
類型的常量(文字)指定正確后綴的可移植方式。
當您處理常量時,所有計算都將由編譯器完成,結果是相同的。
宏附加的后綴( ul
,系統特定)只能用於文字常量。
(uint64_t)
可用於常量和變量值。 使用常量,它將具有與后綴/宏相同的效果,使用不同類型的變量,它可以執行值的截斷或擴展,例如,當從 32 位更改為 64 位時,用 0 填充高位。
如果您使用UINT64_C(1)
或(uint64_t)1
,這是一個品味問題。 宏使您更清楚地知道您正在處理一個常量。
沒有明顯的區別或優勢,這些宏有點多余。 演員表和宏之間有一些細微的差別:
(uintn_t)1
用於預處理器目的可能很麻煩,而UINTN_C(1)
擴展為單個 pp 令牌。
UINTN_C
的結果類型實際上是uint_leastn_t
而不是uintn_t
。 所以它不一定是你期望的類型。
如果您在代碼中鍵入1
而不是1u
,則用於 MISRA-C 等編碼標准的 Static 分析器可能會抱怨,因為無論大小如何,移動有符號整數都不是一個好主意。
(uint64_t)1u
符合 MISRA, UINT64_c(1)
可能不符合,或者至少分析器無法分辨,因為它無法像編譯器那樣擴展 pp 令牌。 而且UINT64_C(1u)
可能不起作用,因為這個宏實現可能看起來像這樣:
#define UINT64_C(n) ((uint_least64_t) n ## ull) // BAD: 1u##ull = 1uull
一般來說,我建議使用顯式強制轉換。 或者更好地將所有這些包裝在一個命名常量中:
#define MY_BIT ( (uint64_t)1u << 60 )
UINT64_C(1)
通過令牌粘貼生成單個令牌,而((uint64_t)1)
是具有相同值的常量表達式。
它們可以在發布的示例代碼中互換使用,但不能在預處理器指令(如#if
表達式)中使用。
XXX_C
宏應用於定義可在#if
表達式中使用的常量。 僅當常量必須具有特定類型時才需要它們,否則只需將常量拼寫為沒有后綴的十進制或十六進制就足夠了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.