爲了獲得最大的兩個數字,我有以下宏以下哪個宏是安全的,爲什麼?
#define max(a,b) ((a) > (b) ? (a) : (b))
#define maxint(a,b) ({int _a = (a), _b = (b); _a > _b ? _a : _b; })
是什麼都上方的區別。哪一個更好用,爲什麼。我發現這些宏的信息here。但無法理解它。
爲了獲得最大的兩個數字,我有以下宏以下哪個宏是安全的,爲什麼?
#define max(a,b) ((a) > (b) ? (a) : (b))
#define maxint(a,b) ({int _a = (a), _b = (b); _a > _b ? _a : _b; })
是什麼都上方的區別。哪一個更好用,爲什麼。我發現這些宏的信息here。但無法理解它。
第二個宏是安全的,但使用由海灣合作委員會提供的非標準C擴展會發生什麼:statement expressions。但第一個表達是「通用」。使用typeof擴展GCC將有助於:
#define mymax(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); \
_a > _b ? _a : _b; })
要針對JaredPar's answer提出的問題打,你可以使用預處理concatenation和GCC具體__COUNTER__
(或僅僅是較爲標準__LINE__
),例如
#define mymax_counted(a,b,c) ({typeof(a) _a##c = (a); \
typeof(b) _b##c = (b); \
_a##c > _b##c ? _a##c : _b##c; })
#define mymax(a,b) mymax_counted(a,b,__COUNTER__)
但即使這樣也不是完全失效的證明(與壞運氣,能像mymax(_a123,_b123)
一些調用衝突如果唯一__COUNTER__
恰好是123當時)。
事實上,使用inline function更好(因爲如果你調用mymaxfun(i++,t[i])
的行爲是明確界定,並給出了相同的結果mymaxfun(t[i],i++)
,因爲優化編譯器會產生代碼爲高效使用宏時):
static inline int mymaxfun(int a, int b) { return (a>b)?a:b; }
不幸的是,C沒有通用功能(考慮將其切換爲C++及其templates並使用std::max);然而C11具有使用_Generic
關鍵字
宏是非常有用(掌握時)類型的通用表達式,但調用宏時,你應該非常小心副作用的參數(如mymax(i++,t[--i]++)
),所以你總是應該關心和文件如果名稱是一個宏或其他東西(如函數)。作爲一個經驗法則,避免副作用 - 在函數調用查找表達式(包括函數調用和宏調用)中,也包括++
或--
以及其他許多其他函數。
查看源代碼的預處理器擴展形式;因此對於foo.c
源代碼,運行gcc -C -E foo.c > foo.i
(添加諸如-I
,-D
等的任何預處理器選項都是相關的),並在foo.i
與less foo.i
;它總是有啓發性的。
唯一的問題是當有人試圖用漂浮物來使用它。 – woolstar
第二個宏更安全,因爲它只對輸入進行一次評估。如果輸入是具有副作用的表達式,這一點很重要
max(i++, --j);
請注意,我說的更安全和不安全。這個宏仍然有可能是不正確的,因爲可能有當地人在範圍內已經命名爲_a
和_
b。試想一下,如果下面是執行
int _a = 42;
int _b = 13;
maxint(_a, _b);
這將拓展出
int _a = 42;
int _b = 13;
{int _a = (_a), _b = (_b); _a > _b ? _a : _b; })
好的一點,雖然我注意到這是一個非常不好的編程習慣,爲了這個確切的原因開始一個帶下劃線的局部變量。 –
兩者都不安全。請避免使用非標準C擴展如表達式語句的宏實現,如果您需要將代碼移植到其他平臺,將會給您帶來各種麻煩。盡我所能從成爲一個咆哮來表達這個答案,在我看來,max
宏是C標準庫中最糟糕的事情之一,因爲它有潛在的副作用。在過去,我已經#undef
ed max
只是爲了安全起見。
您最好將第二個宏maxint
編碼爲一個函數,因爲它具有宏的所有缺點(例如,不容易調試,實例化的變量與本地衝突)但沒有任何好處(例如泛化)。
替代:
我最喜歡的:使用三元在線:a > b ? a : b
您可以放置在括號的味道,因爲你知道到底是怎麼回事。它也會比通過獲取價值副本來嘗試安全的宏更快。
構建您自己的功能。考慮爲整數類型定義max
併爲浮點定義fmax
。 abs
和fabs
已經有了先例。
AFAIK,'max'不在C標準庫中...... –
想想用max(++ i, - j)'來預處理器產生了什麼。 *既不*是「安全的」,但後者不像宏觀參數擴展那樣容易產生副作用。 – WhozCraig
其次更安全。例如調用'max(i ++,j ++)'或者就此而言,'max(fn1(),fn2())' – anishsane
請注意,這些宏中的第二個使用'gcc'擴展(將塊語句視爲表達式)並且因此不便攜。 – templatetypedef