?
本文檔使用 PHP中文網(wǎng)手冊 發(fā)布
不符合任何其他主要類別的運營商的集合。
操作者 | 運營商名稱 | 例 | 描述 |
---|---|---|---|
(...) | 函數(shù)調(diào)用 | F(...) | 使用零個或多個參數(shù)調(diào)用函數(shù)f() |
, | 逗號運算符 | a,b | 評估表達式a,忽視其返回值并完成任何副作用,然后評估表達式b,返回此評估的類型和結(jié)果 |
(類型) | 類型轉(zhuǎn)換 | (類型)的 | 將類型轉(zhuǎn)換為類型 |
? : | 條件運算符 | 一個 ?b:c | 如果a在邏輯上為真(不評估為零),則評估表達式b,否則評估表達式c |
的sizeof | 規(guī)模經(jīng)營者 | sizeof a | 一個字節(jié)的大小 |
_Alignof(自C11以來) | _Alignof運營商 | _Alignof(類型) | 類型所需的對齊 |
函數(shù)調(diào)用表達式具有表單。
expression ( argument-list(optional) ) |
---|
其中
表達 | - | 指針函數(shù)類型的任何表達式(在左值轉(zhuǎn)換之后) |
---|---|---|
參數(shù)列表 | - | 任何完整對象類型的逗號分隔的表達式列表(不能是逗號運算符)。調(diào)用不帶參數(shù)的函數(shù)時可能會被省略。 |
函數(shù)調(diào)用表達式的行為取決于被調(diào)用函數(shù)的原型是否在調(diào)用點范圍內(nèi)。
1)參數(shù)的數(shù)量必須等于參數(shù)的數(shù)量(除非使用省略號參數(shù))。
2)每個參數(shù)的類型都必須是一種類型,以便隱式轉(zhuǎn)換,就像通過賦值存在將相應(yīng)參數(shù)的非限定類型轉(zhuǎn)換為參數(shù)類型一樣。
此外,對于在and之間使用關(guān)鍵字static的數(shù)組類型的每個參數(shù),參數(shù)表達式都必須指定一個指向數(shù)組元素的指針,該數(shù)組元素至少具有參數(shù)大小表達式中指定的許多元素。 | (自C99以來) |
---|
3)參數(shù)以未指定的順序進行評估,無需排序。
4)賦值(直到C11)執(zhí)行初始化(從C11開始),將每個參數(shù)的值復(fù)制到相應(yīng)的函數(shù)參數(shù)(注意;該函數(shù)可以修改其參數(shù),并且這些更改不會影響參數(shù); C函數(shù)調(diào)用只是調(diào)用 - 值)。
如果存在尾部省略號參數(shù),則對剩余參數(shù)執(zhí)行默認參數(shù)提升,這些參數(shù)可用va_list
。
5)函數(shù)被執(zhí)行,并且它返回的值成為函數(shù)調(diào)用表達式的值(如果函數(shù)返回void,則函數(shù)調(diào)用表達式是一個void表達式)
void f(char* p, int x) {}int main(void){ f("abc", 3.14); // array to pointer and float to int conversions}
1)參數(shù)以未指定的順序進行評估并且沒有排序。
2)在每個參數(shù)表達式上執(zhí)行默認參數(shù)促銷。
3)賦值(直到C11)執(zhí)行初始化(從C11開始),將每個自變量的值復(fù)制到相應(yīng)的函數(shù)參數(shù)中。
4)函數(shù)被執(zhí)行,并且它返回的值成為函數(shù)調(diào)用表達式的值(如果函數(shù)返回void,則函數(shù)調(diào)用表達式是一個void表達式)
void f(); // no prototypeint main(void){ f(1, 1.0f); // UB unless f is defined to take an int and a double}void f(int a, double c) {}
沒有原型的函數(shù)調(diào)用函數(shù)的行為是未定義的。
參數(shù)的數(shù)量與參數(shù)的數(shù)量不匹配。
提升的參數(shù)類型與除了那些參數(shù)的提升類型不兼容
如果參數(shù)的值可由兩種類型表示,則認為兼容的相同整數(shù)類型的有符號和無符號版本是兼容的。
指向void的指針和指向(可能是cvr限定的)字符類型的指針被認為是兼容的
指定要調(diào)用的函數(shù)的表達式的評估和所有參數(shù)相對于彼此是不相關(guān)的(但是在函數(shù)的主體開始執(zhí)行之前有一個序列點)。
(*pf[f1()]) (f2(), f3() + f4()); // f1, f2, f3, f4 may be called in any order
盡管函數(shù)調(diào)用只是為指向函數(shù)的指針定義的,但由于函數(shù)到指針的隱式轉(zhuǎn)換,它可以與函數(shù)指示符一起工作。
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}
忽略未使用參數(shù)的函數(shù)(如printf
,)必須在范圍內(nèi)使用原型調(diào)用(此類函數(shù)的原型必須使用尾部省略號參數(shù))以避免調(diào)用未定義的行為。
C11之后的缺陷報告DR 427在調(diào)用具有原型的函數(shù)時,為了允許const限定類型的參數(shù)(事實上允許),從賦值到初始化相應(yīng)的參數(shù),改變了準備函數(shù)參數(shù)的語義。允許的隱式轉(zhuǎn)換保留隱式轉(zhuǎn)換,就像通過賦值一樣,因為這是初始化也使用的。
一個函數(shù)調(diào)用表達式,其中表達式完全由一個標識符組成,并且該標識符未聲明,就像標識符被聲明為一樣。extern int identifier(); //返回int并且沒有原型所以下面的完整程序是有效的C89:main(){int n = atoi(“123”); //隱式聲明atoi為int atoi()} | (直到C99) |
---|
逗號運算符表達式具有表單。
lhs , rhs |
---|
其中
LHS | - | 任何表達 |
---|---|---|
RHS | - | 除另一個逗號運算符以外的任何表達式(換句話說,逗號運算符的結(jié)合性是從左到右的) |
首先,評估左操作數(shù)lhs,并丟棄其結(jié)果值。
然后,發(fā)生一個序列點,以使lhs的所有副作用都完成。
然后,評估右操作數(shù)rhs,并將其結(jié)果作為非左值由逗號運算符返回。
lhs的類型可能是void
(也就是說,它可能是對返回的函數(shù)的調(diào)用void
,或者它可能是一個表達式void
)。
逗號運算符可能是C ++中的左值,但從不C中。
逗號運算符可以返回一個結(jié)構(gòu)(唯一的其他返回結(jié)構(gòu)的表達式是復(fù)合文字,函數(shù)調(diào)用,賦值和條件運算符)。
在以下上下文中,逗號運算符不能出現(xiàn)在表達式的頂級,因為逗號具有不同的含義:
函數(shù)調(diào)用中的參數(shù)列表
初始化器表達式或初始化器列表
通用選擇
如果逗號運算符必須在這種情況下使用,則必須加上括號:
// int n = 2,3; // error, comma assumed to begin the next declarator// int a[2] = {1,2,3}; // error: more declarators than elementsint 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
頂級逗號運算符也被禁止在數(shù)組邊界內(nèi)。
// int a[2,3]; // errorint 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
請參閱 cast 操作。
條件運算符表達式具有該形式。
condition ? expression-true : expression-false |
---|
其中
condition | - | an expression of scalar type |
---|---|---|
expression-true | - | the expression that will be evaluated if condition compares unequal to zero |
expression-false | - | the expression that will be evaluated if condition compares equal to zero |
只有以下表達式被允許為expression-true和expression-false。
任何算術(shù)類型的兩個表達式
相同結(jié)構(gòu)或聯(lián)合類型的兩個表達式
void類型的兩個表達式
指針類型的兩個表達式,指向兼容的類型,忽略cvr限定符
一個表達式是一個指針,另一個是空指針常量(如NULL
)
一個表達式是一個指向?qū)ο蟮闹羔?,另一個是指向void的指針(可能是合格的)
1)首先,評估狀況。評估后有一個順序點。
2)如果條件的結(jié)果不等于零,則執(zhí)行表達式真,否則執(zhí)行異常錯誤
3)執(zhí)行從評估結(jié)果到通用類型的轉(zhuǎn)換,定義如下:
1)如果表達式具有算術(shù)類型,則通用類型是常規(guī)算術(shù)轉(zhuǎn)換后的類型
2)如果表達式具有struct / union類型,則通用類型是該結(jié)構(gòu)/聯(lián)合類型
3)如果表達式都是無效的,整個條件運算符表達式就是一個void表達式
4)如果一個是指針而另一個是空指針常量,則該類型是該指針的類型
5)如果兩者都是指針,則結(jié)果是指向組合指向類型的cvr限定符的類型的指針(即,如果一個是const int*
另一個volatile int*
,則結(jié)果是const volatile int*
),并且如果類型不同,指向類型是復(fù)合類型。
6)如果一個指向void的指針,則結(jié)果是一個指向無效且具有組合的cvr限定符的指針
條件運算符永遠不是左值表達式,盡管它可能會返回struct / union類型的對象。唯一可能返回stucts的其他表達式是賦值,逗號,函數(shù)調(diào)用和復(fù)合文字。
請注意,在C ++中,它可能是一個左值表達式。
有關(guān)此運算符和賦值的相對優(yōu)先級的詳細信息,請參閱運算符優(yōu)先級。
條件運算符具有從右到左的關(guān)聯(lián)性,這允許鏈接。
struct vehicle v = arg == 'B' ? bus : arg == 'A' ? airplane : arg == 'T' ? train : arg == 'C' ? car : arg == 'H' ? horse : feet;
請參閱sizeof運算符。
參見對齊操作符。