其他運算子
不屬於任何其他主要類別的運算子集合。
本節不完整 原因:考慮為此表和其他涵蓋多個主題的表提供更通用的目錄 |
運算子 | 運算子名稱 | 示例 | 描述 |
---|---|---|---|
(...) | 函式呼叫 | f(...) | 呼叫函式 f(),帶零個或多個引數 |
, | 逗號運算子 | a, b | 計算表示式 a,忽略其返回值並完成任何副作用,然後計算表示式 b,返回此計算的型別和結果 |
(type) | 型別轉換 | (type)a | 將 a 的型別轉換為 type |
? : | 條件運算子 | a ? b : c | 如果 a 邏輯上為真(不評估為零),則計算表示式 b,否則計算表示式 c |
sizeof | sizeof 運算子 | sizeof a | a 的大小(以位元組為單位) |
_Alignof (C11 起) |
_Alignof 運算子 | _Alignof(type) | type 所需的對齊方式 |
typeof | typeof 運算子 | typeof(a) | a 的型別 |
目錄 |
[編輯] 函式呼叫
函式呼叫表示式的形式為
表示式 ( 引數列表 (可選) ) |
|||||||||
其中
表示式 | - | 任何指向函式型別的表示式(在左值轉換之後) |
引數列表 | - | 由逗號分隔的任何完整物件型別的表示式列表(不能是逗號運算子)。呼叫不帶引數的函式時可以省略。 |
函式呼叫表示式的行為取決於被呼叫函式的原型在呼叫點是否在作用域內。
[編輯] 帶原型的函式呼叫
(C99 起) |
void f(char* p, int x) {} int main(void) { f("abc", 3.14); // array to pointer and float to int conversions }
不帶原型的函式呼叫1) 實參以未指定順序且不帶序列化地進行評估。
2) 對每個實參表示式執行預設實參提升。
3) 執行賦值以將每個實參的值複製到相應的函式引數,忽略引數型別及其可能遞迴的元素或成員(如果有)上的任何型別限定符。
4) 函式執行,其返回值成為函式呼叫表示式的值(如果函式返回 void,則函式呼叫表示式是 void 表示式)
void f(); // no prototype int main(void) { f(1, 1.0f); // UB unless f is defined to take an int and a double } void f(int a, double c) {} 如果出現以下情況,呼叫不帶原型的函式的行為是未定義的:
|
(直至 C23) |
[編輯] 注意
指定被呼叫函式的表示式的評估和所有實參的評估相互之間未序列化(但在函式體開始執行之前存在一個序列點)
(*pf[f1()]) (f2(), f3() + f4()); // f1, f2, f3, f4 may be called in any order
儘管函式呼叫僅針對指向函式的指標定義,但由於函式到指標隱式轉換,它適用於函式指示符。
int f(void) { return 1; } int (*pf)(void) = f; int main(void) { f(); // convert f to pointer, then call (&f)(); // create a pointer to function, then call pf(); // call the function (*pf)(); // obtain the function designator, convert to pointer, then calls (****f)(); // convert to pointer, obtain the function, repeat 4x, then call (****pf)(); // also OK }
忽略未使用實參的函式,例如 printf,必須在原型作用域內呼叫(此類函式的原型必然使用尾隨省略號引數)以避免呼叫未定義行為。
當前標準中關於準備函式引數語義的措辭存在缺陷,因為它規定引數在呼叫時從實參賦值,這錯誤地拒絕了 const-qualified 引數或成員型別,並且不恰當地應用了 volatile 的語義,這在許多平臺上無法為函式引數實現。C11 後的缺陷報告 DR427 提出將此類語義從賦值更改為初始化,但被關閉為非缺陷。
函式呼叫表示式中,如果表示式完全由一個識別符號組成,並且該識別符號未宣告,則其行為如同該識別符號宣告為 extern int identifier(); // returns int and has no prototype 因此,以下完整程式是有效的 C89 main() { int n = atoi("123"); // implicitly declares atoi as int atoi() } |
(直到 C99) |
[編輯] 逗號運算子
逗號運算子表示式的形式為
lhs , rhs |
|||||||||
其中
lhs | - | 任何表示式 |
rhs | - | 任何表示式,除了另一個逗號運算子(換句話說,逗號運算子的結合性是從左到右的) |
首先,評估左運算元lhs,並丟棄其結果值。
然後,發生一個序列點,以便lhs的所有副作用都完成。
然後,評估右運算元rhs,其結果由逗號運算子作為非左值返回。
[編輯] 注意
lhs 的型別可以是 void(也就是說,它可以是對返回 void 的函式的呼叫,或者它可以是將表示式強制轉換為 void 的表示式)
逗號運算子在 C++ 中可能是左值,但在 C 中永遠不是
逗號運算子可以返回一個結構體(唯一返回結構體的其他表示式是複合字面量、函式呼叫、賦值和條件運算子)
在以下上下文中,逗號運算子不能出現在表示式的頂層,因為逗號具有不同的含義
如果逗號運算子必須在此類上下文中使用,則必須將其用括號括起來
// int n = 2,3; // error, comma assumed to begin the next declarator // int a[2] = {1,2,3}; // error: more initializers than elements int n = (2,3), a[2] = {(1,2),3}; // OK f(a, (t=3, t+2), c); // OK, first, stores 3 in t, then calls f with three arguments
頂層逗號運算子也不允許在陣列邊界中使用
// int a[2,3]; // error int a[(2,3)]; // OK, VLA array of size 3 (VLA because (2,3) is not a constant expression)
逗號運算子不允許在常量表達式中使用,無論它是否在頂層
// static int n = (1,2); // Error: constant expression cannot call the comma operator
[編輯] 轉換運算子
參見轉換運算子
[編輯] 條件運算子
條件運算子表示式的形式為
條件 ? 表示式-真 : 表示式-假 |
|||||||||
其中
條件 | - | 標量型別的表示式 |
表示式-真 | - | 如果條件與零不相等,則評估的表示式 |
表示式-假 | - | 如果條件與零相等,則評估的表示式 |
只允許以下表達式作為表示式-真和表示式-假
|
(自 C23 起) |
(自 C23 起) |
#define ICE(x) (sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1))) // if x is an Integer Constant Expression then macro expands to sizeof(*(1 ? NULL : (int *) 1)) // (void *)((x)*0l)) -> NULL // according to point (4) this further converts into sizeof(int) // if x is not an Integer Constant Expression then macro expands to // according to point (6) (sizeof(*(void *)(x)) // Error due incomplete type
[編輯] 注意
條件運算子絕不是左值表示式,儘管它可能返回結構體/聯合體型別的物件。唯一可能返回結構體的其他表示式是賦值、逗號、函式呼叫和複合字面量。
請注意,在 C++ 中,它可能是左值表示式。
有關此運算子和賦值的相對優先順序的詳細資訊,請參閱運算子優先順序。
條件運算子具有從右到左的結合性,這允許鏈式操作
#include <assert.h> enum vehicle { bus, airplane, train, car, horse, feet }; enum vehicle choose(char arg) { return arg == 'B' ? bus : arg == 'A' ? airplane : arg == 'T' ? train : arg == 'C' ? car : arg == 'H' ? horse : feet ; } int main(void) { assert(choose('H') == horse && choose('F') == feet); }
[編輯] sizeof
運算子
[編輯] _Alignof
運算子
[編輯] typeof
運算子
[編輯] 參考文獻
- C23 標準 (ISO/IEC 9899:2024)
- 6.5.2.2 函式呼叫 (p: 待定)
- 6.5.3.4 sizeof 和 _Alignof 運算子 (p: 待定)
- 6.5.4 轉換運算子 (p: 待定)
- 6.5.15 條件運算子 (p: 待定)
- 6.5.17 逗號運算子 (p: 待定)
- 6.7.3.5 Typeof 說明符 (p: 115-118)
- C17 標準 (ISO/IEC 9899:2018)
- 6.5.2.2 函式呼叫 (p: 58-59)
- 6.5.3.4 sizeof 和 _Alignof 運算子 (p: 64-65)
- 6.5.4 轉換運算子 (p: 65-66)
- 6.5.15 條件運算子 (p: 71-72)
- 6.5.17 逗號運算子 (p: 75)
- C11 標準 (ISO/IEC 9899:2011)
- 6.5.2.2 函式呼叫 (p: 81-82)
- 6.5.3.4 sizeof 和 _Alignof 運算子 (p: 90-91)
- 6.5.4 轉換運算子 (p: 91)
- 6.5.15 條件運算子 (p: 100)
- 6.5.17 逗號運算子 (p: 105)
- C99 標準 (ISO/IEC 9899:1999)
- 6.5.2.2 函式呼叫 (p: 71-72)
- 6.5.3.4 sizeof 運算子 (p: 80-81)
- 6.5.4 轉換運算子 (p: 81)
- 6.5.15 條件運算子 (p: 90-91)
- 6.5.17 逗號運算子 (p: 94)
- C89/C90 標準 (ISO/IEC 9899:1990)
- 3.3.2.2 函式呼叫
- 3.3.3.4 sizeof 運算子
- 3.3.4 轉換運算子
- 3.3.15 條件運算子
- 3.3.17 逗號運算子
[編輯] 另請參見
常見運算子 | ||||||
---|---|---|---|---|---|---|
賦值 | 遞增 遞減 |
算術 | 邏輯 | 比較 | 成員 訪問 |
其他 |
a = b |
++a |
+a |
!a |
a == b |
a[b] |
a(...) |
C++ 文件,關於 其他運算子
|