[英]Typedefs and printf format specifiers
typedef的一個常見用途是使變量的“類型”能夠更好地了解變量的用途,而無需重新定義其后面的存儲結構。
但是,我也看到typedef是一種改變一類變量的存儲結構的方法。
例如,如果我定義
typedef uint32_t my_offset_t
並且具有my_offset_t
類型的my_offset_t
,將代碼庫從uint32_t
切換到char
或uint64_t
就像更改一行並重新編譯一樣簡單(假設我使用的是sizeof
而不是硬編碼的大小), 除了printf /的情況scanf 。
有沒有辦法根據類型以一種簡單的方式交換格式說明符,沒有printf
/ scanf
,if-elses或ifdefs的包裝函數?
謝謝!
對於任何感興趣的人,我正在修改一個使用16位偏移來處理32位偏移的LKM,但是如果需要的話,希望能夠以最小的變化進行64位(或其他!)偏移。
這是一項棘手的業務,但C99及后來的<inttypes.h>
顯示了這樣做的方法。
對於每個定義的類型,您需要為自己提供一組適當的'PRI'和'SCN'宏,小心避免使用標准化的命名空間。
例如,您可以將XYZ用作項目特定的前綴,並生成:
XYZ_PRIx_my_offset_t
XYZ_PRId_my_offset_t
XYZ_PRIX_my_offset_t
XYZ_PRIu_my_offset_t
XYZ_PRIo_my_offset_t
和SCN等價物。 此外,您可以根據基類型的等效宏來定義它們,因此:
#define XYZ_PRIx_my_offset_t PRIx32
#define XYZ_PRId_my_offset_t PRId32
#define XYZ_PRIX_my_offset_t PRIX32
#define XYZ_PRIu_my_offset_t PRIu32
#define XYZ_PRIo_my_offset_t PRIo32
在您的代碼中,使用XYZ_PRIx_my_offset_t
宏構建格式字符串:
printf("Offset: 0x%.8" XYZ_PRIX_my_offset_t "\n", my_offset_value);
如果您隨后需要將所有內容更改為64位,則可以適當地編輯typedef和宏定義,其余代碼保持“不變”。 如果你真的很小心,你可以非常接近完全不變。
確保在設置了大量警告的32位和64位系統上進行編譯。 GCC不會對您當前平台上的非問題發出警告,但它們可能會出現在另一個平台上。 (我剛剛修復了一些在64位上干凈但在32位上不干凈的代碼;它現在使用像XYZ_PRId_int4
這樣的宏而不是%d
並在兩者上干凈地編譯。)
如果您查看我之前關於inttypes.h的問題,您可以看到系統定義的格式說明符如何與typedef(通過#define
)一起使用,以便為您的自定義類型創建自定義打印說明符。
另一種解決方案是轉換和從intmax_t
有符號類型和uintmax_t
的無符號類型。 例如:
printf("%ju\n", (uintmax_t)n);
如果n
是任何無符號類型,則將正常工作。
對於*scanf()
函數,您必須讀入臨時對象然后分配。
(這假設您的運行時庫支持這些功能。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.