2017-03-22 105 views
-3

我已經解決宏(這是一個微控制器,使訪問物理地址是OK),打破了這個(有條件定義的長序列後,屬性等):比較C宏

#define ADDR_A (*18) 
#define ADDR_B (*30) 
#define ADDR_C (*18) 

我想對它們進行比較,所以我可以優化編譯:

#if ADDR_A==ADDR_C 
    return 1; 
#else 
    return 0; 
#endif 

,但我得到「錯誤:運營商‘*’沒有左操作數」,這是有道理的。是否可以比較宏的定義。我有一種預感,我可以將它們轉換爲字符串來進行比較,但是我沒有找到一種方法(就像使用#作爲宏參數)。

不,我不想在運行時執行此操作,因爲我正在計算週期。

+4

這是無效的C.編譯器應該如何知道它是一個地址和該對象的類型?你的問題的其餘部分不清楚。你想比較哪些doy,爲什麼?它聞起來像一個XY-問題。 – Olaf

+0

我完全同意@Olaf。另外,如果表達式只有字面常量(如果要比較兩個存儲器映射寄存器的地址,那麼我所用的所有C編譯器都會優化一個普通的'if'語句;而且,由於您使用的是微控制器,因此無論如何您都應該啓用優化。換句話說,不需要依賴*預處理器*來優化相關的代碼;任何一半體面的C編譯器都可以爲你做(如果你使用正常的C if語句)。 –

回答

1

你不能在一個#if比較字符串,因爲:

  • 你只能使用常量表達式使用#if
  • 串,只能用一個迴路或功能
  • 循環AREN」進行比較噸常量表達式
  • 和:

    Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated. (C11, 6.6P3)

我能想到的最好的是分裂的地址和非關聯到兩個不同的宏,如:

#define ADDR_A (18) 
#define ADDR_B (30) 
#define ADDR_C (18) 
#define GET_A (*ADDR_A) 
#define GET_B (*ADDR_B) 
#define GET_C (*ADDR_C) 

#if ADDR_A == ADDR_B 
return 1 
#else 
return 0 
#endif 

注意檢查常量的平等「在運行時」將幾乎所有的編譯器可被忽略值得它的鹽;在this example中,編譯器只生成等效的return 1,因爲它在編譯時知道條件將評估爲false;計數週期在這裏是一個紅鯡魚,因爲這些比較將被消除。我不確定你是如何使用這些宏的(我不能在頭腦中構造一個它們在句法上有效的例子),但是我有一種感覺,你的代碼會如果您只是讓宏包含地址,並且在代碼中內聯取消引用這些地址,則更容易理解。如果我讀你的代碼,我會更喜歡:

#define ADDR_A (18) 
#define ADDR_B (30) 
#define ADDR_C (18) 

if (ADDR_A == ADDR_B) 
    return 1 
return 0 
1

如何只將地址放入宏中,並分別輸入類型信息?

#define ADDR_A (18) 
#define ADDR_B (30) 
#define ADDR_C (18) 

unsigned uint16_t *A = (uint16_t*)ADDR_A; 
unsigned uint16_t *B = (uint16_t*)ADDR_B; 
unsigned uint16_t *C = (uint16_t*)ADDR_C; 

然後你可以使用你的測試。

另外,跳過預處理器,只是做在C:

unsigned uint16_t *const A = (uint16_t*)18; 
unsigned uint16_t *const B = (uint16_t*)30; 
unsigned uint16_t *const C = (uint16_t*)18; 

int f() 
{ 
    if (A == C) 
     return 1; 
    else 
     return 0; 
} 

除非你有一個非常低質量的編譯器,你可以期望它承認A==C作爲一個常量表達式和簡化代碼相應。