2012-02-25 52 views
2

如果編譯器知道它們是常量,我想使用gcc對函數輸入執行一些編譯時檢查。GCC常量函數輸入的編譯時檢查

我有一個解決方案,非常接近的作品,而據我所知,它應該工作。

注意:__builtin_constant_p(表達式)應該返回一個表達式在編譯時是否是一個常量。

假設我們要檢查是否端口< 2調用UART(端口)時,下面的代碼應該工作:

#include <stdio.h> 

void _uart(int port) { 
printf("port is %d", port); 
} 

#define uart(port) \ 
static_assert(__builtin_constant_p(port)? port<2: 1, "parameter port must be < 2"); \ 
_uart(port) 

int main(void) { 
int x=1; 
uart(x); 
} 

調用UART時,該作品()。不幸的是,它不適用於非常量x。出於某種原因,static_assert不能處理x不是常量的情況,即使理論上__builtin_constant_p()甚至不會傳遞它一個常量。我得到的錯誤消息是:

c:\>gcc a.cpp -std=c++0x -Os 
a.cpp: In function 'int main()': 
a.cpp:13: error: 'x' cannot appear in a constant-expression 

任何想法?

+0

「出於某種原因」,「常量表達式」的形式語法對於「?」運算符沒有規則:「如果在編譯時左手邊可證明爲」假「,那麼第二個參數不需要是一個常量表達式。「 「常量表達式」的語法表示「所有組件(甚至最終在評估時不使用的組件)都必須是常量表達式。」這就是爲什麼錯誤消息說「不能出現在常量表達式中」而不是「不能出現在常量表達式的評估部分」。 – 2012-02-25 16:47:08

回答

1

你可以嘗試在Linux內核中使用的伎倆:

What is ":-!!" in C code?

(有點可怕)Linux內核宏是關於允許在參數什麼樣的表情不那麼嚴格。

+0

這適用於C,但不適用於C++。 – Berwyn 2012-02-26 23:55:32

2

您的代碼可以與g ++(GCC)配合使用4.8.2。

- 但沒有進行優化,正如您正確指出的那樣。

如果我們能使用

static_assert(__builtin_choose_expr(__builtin_constant_p(port), \ 
          port<2, 1), "parameter port must be < 2") 

- 可惜__builtin_choose_expr結構是目前僅適用於C.

然而,有一個C++ patch這可悲的是沒能到尚未發佈。

+1

嗯......你說得對,但它並沒有真正做我想做的事,因爲我忘了添加編譯器優化參數:現在我添加了「-Os」,它很好地再現了問題。 – Berwyn 2014-03-13 20:19:20