在gnu c 中,用括號將複合語句括起來也形成了表示式。他允許你在一個表示式內使用迴圈,跳轉和區域性變數。
一個複合語句是用大括號{}括起來的一組語句。在包含語句的表示式這種結構中,再用括號( )將大括號括起來,例如:
({ int y = foo (); int z;
if (y > 0) z = y;
else z = – y;
z; })
就是一個合法表示式,用於計算foo( )函式返回值的絕對值。
在上面的複合語句中,最後的一句必須是一個以分號結尾的表示式。這個表示式代表了整個結構的值。如果你在大括號裡的最後一句用的是其他的語句,則整個結構的返回型別為void,即沒有合法的返回值。
這種特性使得巨集定義變得更加安全(因為每個運算元都只被計算一次,例如++運算)。例如計算最大值通常在c語言中被定義為這樣的巨集:
#define max(a,b) ((a) > (b) ? (a) : (b))
但是其中的a和b可能會被計算兩次,如果運算元帶有副作用,則會產生錯誤的結果。在gnu c中,如果你知道了運算元的型別(假設為int),你可以這樣安全的定義巨集:
#define maxint(a,b)
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
語句內嵌在常量表示式(例如列舉型別),位域尺寸或靜態變數初始化中是不允許的。如果你不知道運算元的型別,你也可以使用typeof來獲得型別。
語句表示式內嵌在g++中並不支援,而且將來是否支援目前也不清楚(他們在某時被完全支援或者被拋棄掉,或者作為bug會一直存在)。就目前而言,語句內嵌表示式在預設情況下工作的並不好。
此外,在c++中語句內嵌表示式還存在很多語義問題。如果你希望在c++中用語句內嵌表示式來代替行內函數(inline function),物件的析構處理可能會讓你驚訝。例如:
#define foo(a) ({int b = (a); b + 3; })
並不等同於
inline int foo(int a) { int b = a; return b + 3; }
具體而言,當傳遞給foo的表示式的會引入臨時物件的生成的時候,這些臨時物件的析構在用巨集時會早於用函式的情況。
以上情況說明在用於c++程式碼的.h標頭檔案中使用語句內聯表示式並不是一個好主意。一些gnu c的庫的某些版本中的使用語句內聯表示式的標頭檔案已經造成了這樣的bug。