簡體   English   中英

C宏:獲得整數常量的最小類型

[英]C Macro: get smallest type for an integer constant

為什么我需要弄清楚文字的小類型(Backstory)

我寫了一組宏來創建和使用fifos。 宏允許在具有靜態內存分配的所有系統上實現通用但仍然非常快速的實現,例如在小型嵌入式系統中。 在codereview上的那些人對我的實現也沒有任何重大問題。

數據被放入匿名struts中,所有數據都由該結構的標識符訪問。 目前,用於創建這些結構的類似函數的宏看起來像這樣

#define _fff_create(_type, _depth, _id)                 \
    struct {uint8_t read; uint8_t write; _type data[_depth];} _id = {0,0,{}}

#define _fff_create_deep(_type, _depth, _id)            \
    struct {uint16_t read; uint16_t write; _type data[_depth];} _id = {0,0,{}}

我正在尋找什么

現在我想將這兩者合並為一個宏。 為此,我要在編譯時計算readwrite索引_depth元素所需的最小大小。 _開頭的參數名稱表示只傳遞文字或#define值,兩者都在編譯時已知。

因此,我希望找到一個宏typeof_literal(arg) ,如果arg <256或uint16_t ,則返回uint8_t

我試過的

  1. GCC 4.9.2。 提供一個名為typeof()的命令。 但是當與任何文字一起使用時,它返回一個int類型,在我的系統上是兩個字節。
  2. GCC 4.9.2的另一個特點是復合語句 typeof(({uint8_t u8 = 1; u8;}))將正確返回uint8_t 但是我無法想出一種方法來為該塊中的類型設置條件:
  3. typeof(({uint8_t u8 = 1; uint16_t u16 = 1; input ? u8 : u16;}))總是返回uint16_t因為?:運算符的類型提升
  4. if(...)也不能使用,因為任何命令都會在“lower”塊中發生
  5. 宏不能包含#if ,這使得它們無法用於此比較。

你不能這樣離開嗎?

我意識到可能沒有解決這個問題的方法。 那也沒關系; 目前的代碼只是一個小小的不便。 然而,我想知道是否有一個棘手的方法來解決這個問題。 解決方案可以為宏開辟新的可能性。 如果您確定無法做到這一點,請解釋原因。

我認為你正在尋找的構建塊是__builtin_choose_expr ,它與三元運算符非常相似,但不會將其結果轉換為通用類型。

#define CHOICE(x) __builtin_choose_expr (x, (int) 1, (short) 2)

這個

printf ("%zu %zu\n", sizeof (CHOICE (0)), sizeof (CHOICE (1)));

將打印

2 4

正如所料。

然而,正如Greg Hewgill指出的那樣,C ++有更好的設施(但它們仍然很難使用)。

正如弗洛里安建議的那樣,我正在尋找的宏確實可以用__builtin_choose_expr編寫。 我的解決方案附在下面,經過測試並確認有效。 根據需要使用它!

#define typeof_literal(_literal)                                                        \
    typeof(__builtin_choose_expr((_literal)>0,                                          \
        __builtin_choose_expr((_literal)<=UINT8_MAX, (uint8_t) 0,                       \
        __builtin_choose_expr((_literal)<=UINT16_MAX, (uint16_t) 0,                     \
        __builtin_choose_expr((_literal)<=UINT32_MAX, (uint32_t) 0, (uint64_t) 0))),    \
        __builtin_choose_expr((_literal)>=INT8_MIN, (int8_t) 0,                         \
        __builtin_choose_expr((_literal)>=INT16_MIN, (int16_t) 0,                       \
        __builtin_choose_expr((_literal)>=INT32_MIN, (int32_t) 0, (int64_t) 0)))))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM