名稱空間
變體
操作

其他運算子

來自 cppreference.com
< c‎ | 語言

不屬於任何其他主要類別的運算子集合。

運算子 運算子名稱 示例 描述
(...) 函式呼叫 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 的型別

目錄

[編輯] 函式呼叫

函式呼叫表示式的形式為

表示式 ( 引數列表 (可選) )

其中

表示式 - 任何指向函式型別的表示式(在左值轉換之後)
引數列表 - 由逗號分隔的任何完整物件型別的表示式列表(不能是逗號運算子)。呼叫不帶引數的函式時可以省略。

函式呼叫表示式的行為取決於被呼叫函式的原型在呼叫點是否在作用域內

[編輯] 帶原型的函式呼叫

1) 引數數量必須等於實引數量(除非使用省略號引數)。
2) 每個引數的型別必須是這樣一種型別:存在如同賦值的隱式轉換,將相應實參的非限定型別轉換為引數的型別。
此外,對於在 [] 之間使用關鍵字 static 的每個陣列型別引數,實參表示式必須指定一個指向陣列元素的指標,該陣列至少包含引數大小表示式中指定的那麼多元素。
(C99 起)
3) 實參以未指定順序且不帶序列化地進行評估。
4) 執行賦值以將每個實參的值複製到相應的函式引數,忽略引數型別及其可能遞迴的元素或成員(如果有)上的任何型別限定符(注意:函式可以修改其引數,這些更改不會影響實參;C 函式呼叫僅為值傳遞)。
5) 函式執行,其返回值成為函式呼叫表示式的值(如果函式返回 void,則函式呼叫表示式是 void 表示式)
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) {}

如果出現以下情況,呼叫不帶原型的函式的行為是未定義的:

  • 實引數量與引數數量不匹配。
  • 實參的提升型別與引數的提升型別不相容,除非
  • 如果實參的值可以由兩種型別表示,則相同整數型別的有符號和無符號版本被認為是相容的。
  • 指向 void 的指標和指向(可能經過 cvr-限定的)字元型別的指標被認為是相容的
(直至 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

[編輯] 轉換運算子

參見轉換運算子

[編輯] 條件運算子

條件運算子表示式的形式為

條件 ? 表示式-真 : 表示式-假

其中

條件 - 標量型別的表示式
表示式-真 - 如果條件與零不相等,則評估的表示式
表示式-假 - 如果條件與零相等,則評估的表示式

只允許以下表達式作為表示式-真表示式-假

  • 兩個任意算術型別的表示式
  • 兩個相同結構體聯合體型別的表示式
  • 兩個 void 型別的表示式
  • 兩個指標型別的表示式,指向的型別在忽略 cvr-限定符後是相容的
(自 C23 起)
  • 一個表示式是指標,另一個是空指標常量(例如 NULLnullptr_t(C23 起)
  • 一個表示式是指向物件的指標,另一個是指向 void 的指標(可能經過限定)
1) 首先,評估條件。此評估之後有一個序列點
2) 如果條件的結果與零不相等,則執行表示式-真,否則執行表示式-假
3) 對評估結果執行轉換公共型別,定義如下:
1) 如果表示式具有算術型別,則公共型別是常規算術轉換後的型別
2) 如果表示式具有結構體/聯合體型別,則公共型別是該結構體/聯合體型別
3) 如果表示式都為 void,則整個條件運算子表示式是 void 表示式
4) 如果一個是指標,另一個是空指標常量nullptr_t(C23 起),則型別是該指標的型別
5) 如果兩者都是指標,則結果是指向結合了兩個指向型別的 cvr-限定符的型別的指標(即,如果一個是指向 const int*,另一個是指向 volatile int*,則結果是指向 const volatile int* 的指標),如果型別不同,則指向的型別是複合型別
6) 如果一個是指向 void 的指標,則結果是指向 void 的指標,帶有組合的 cvr-限定符
7) 如果兩者都具有 nullptr_t 型別,則公共型別也是 nullptr_t
(自 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 運算子

參見sizeof 運算子

[編輯] _Alignof 運算子

參見_Alignof 運算子

[編輯] typeof 運算子

參見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 += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b

a[b]
*a
&a
a->b
a.b

a(...)
a, b
(type) a
a ? b : c
sizeof


_Alignof
(C11 起)
(直至 C23)

alignof
(自 C23 起)

C++ 文件,關於 其他運算子