?
This document uses PHP Chinese website manual Release
算術(shù)運(yùn)算符將標(biāo)準(zhǔn)的數(shù)學(xué)運(yùn)算應(yīng)用于其操作數(shù)。
Operator | Operator name | Example | Result |
---|---|---|---|
+ | unary plus | +a | the value of a after promotions |
- | unary minus | -a | the negative of a |
+ | addition | a + b | the addition of a and b |
- | subtraction | a - b | the subtraction of b from a |
* | product | a * b | the product of a and b |
/ | division | a / b | the division of a by b |
% | modulo | a % b | the remainder of a divided by b |
~ | bitwise NOT | ~a | the bitwise NOT of a |
& | bitwise AND | a & b | the bitwise AND of a and b |
| | bitwise OR | a | b | the bitwise OR of a and b |
^ | bitwise XOR | a ^ b | the bitwise XOR of a and b |
<< | bitwise left shift | a << b | a left shifted by b |
bitwise right shift | a >> b | a right shifted by b |
無符號(hào)整數(shù)運(yùn)算總是以模2n 來執(zhí)行
其中 n 是該特定整數(shù)中的位數(shù)。例如unsigned int
,添加一個(gè)UINT_MAX
給出0
,并從0
給出中減去一個(gè)UINT_MAX
。
當(dāng)有符號(hào)整數(shù)算術(shù)運(yùn)算溢出(結(jié)果不適合結(jié)果類型)時(shí),行為是未定義的:它可能會(huì)根據(jù)表示規(guī)則(通常是2的補(bǔ)碼)進(jìn)行回繞,它可能陷入某些平臺(tái)或由于編譯器選項(xiàng)(例如-ftrapv
在 GCC 和 Clang中),或者可以由編譯器完全優(yōu)化。
如果 #pragma STDC FENV_ACCESS
設(shè)置為ON
,所有浮點(diǎn)算術(shù)運(yùn)算符服從當(dāng)前浮點(diǎn)舍入方向并報(bào)告 math_errhandling 中指定的浮點(diǎn)算術(shù)錯(cuò)誤,除非部分靜態(tài)初始化程序(在這種情況下不引發(fā)浮點(diǎn)異常并舍入)模式是最近的)。
除非#pragma STDC FP_CONTRACT
設(shè)置為OFF
,否則 所有浮點(diǎn)運(yùn)算都可以像中間結(jié)果具有無限范圍和精度一樣執(zhí)行,即忽略舍入錯(cuò)誤和浮點(diǎn)異常(如果表達(dá)式完全按寫入方式計(jì)算)時(shí)可以觀察到的優(yōu)化。例如,允許(x*y) + z
使用單個(gè)融合乘加CPU指令或優(yōu)化a = x*x*x*x;
as執(zhí)行tmp = x*x; a = tmp*tmp
。
與浮點(diǎn)運(yùn)算無關(guān),浮點(diǎn)運(yùn)算的中間結(jié)果的范圍和精度可能與其類型所指示的不同,請(qǐng)參閱FLT_EVAL_METHOD
。
一元算術(shù)運(yùn)算符表達(dá)式具有這種形式。
| (1) | |
---|---|---|
| (2) |
1)一元加(促銷)
2)一元減號(hào)(否定)
其中
expression | - | expression of any arithmetic type |
---|
一元加號(hào)和一元減號(hào)首先將積分促銷應(yīng)用于它們的操作數(shù),然后。
一元加值返回提升后的值
一元減號(hào)返回提升后的值的負(fù)數(shù)(除了 NaN 的負(fù)數(shù)是另一個(gè) NaN)
表達(dá)式的類型是升級(jí)后的類型,值類別是非左值。
當(dāng)應(yīng)用于,或在典型(2的補(bǔ)碼)平臺(tái)上時(shí)INT_MIN
,由于有符號(hào)整數(shù)溢出,一元減法調(diào)用未定義的行為。LONG_MINLLONG_MIN
在 C ++中,一元運(yùn)算符+也可以與其他內(nèi)置類型(如數(shù)組和函數(shù))一起使用,而在 C 中則不是這樣。
#include <stdio.h>#include <complex.h>int main(void){ char c = 'a'; printf("sizeof char: %zu sizeof int: %zu\n", sizeof c, sizeof +c); printf("-1, where 1 is signed: %d\n", -1); printf("-1, where 1 is unsigned: %u\n", -1u); double complex z = 1 + 2*I; printf("-(1+2i) = %.1f%+.1f\n", creal(-z), cimag(-z));}
可能的輸出:
sizeof char: 1 sizeof int: 4-1, where 1 is signed: -1-1, where 1 is unsigned: 4294967295-(1+2i) = -1.0-2.0
二元附加算術(shù)運(yùn)算符表達(dá)式具有這種形式。
lhs + rhs | (1) | |
---|---|---|
lhs - rhs | (2) |
1)另外:lhs 和 rhs 必須是以下之一
都有算術(shù)類型,包括復(fù)雜和想象
一個(gè)是完成對(duì)象類型的指針,另一個(gè)是整數(shù)類型
2)減法:lhs 和 rhs 必須是以下之一
都有算術(shù)類型,包括復(fù)雜和想象
lhs具有完成對(duì)象類型的指針,rhs具有整數(shù)類型
都是指向兼容類型的完整對(duì)象的指針,忽略限定符
如果兩個(gè)操作數(shù)都有算術(shù)類型,那么。
首先,執(zhí)行通常的算術(shù)轉(zhuǎn)換
然后,按照通常的數(shù)學(xué)規(guī)則(對(duì)于減法,將rhs從lhs中減去),對(duì)轉(zhuǎn)換后的操作數(shù)的值進(jìn)行相加或相減,除了
如果一個(gè)操作數(shù)是 NaN,那么結(jié)果是NaN
無窮大減去無窮大是 NaN 并且FE_INVALID
被提升
無限加上負(fù)的無窮大是 NaN 并且FE_INVALID
被提升
復(fù)數(shù)和虛數(shù)加法和減法的定義如下(注意,如果兩個(gè)操作數(shù)都是虛數(shù),則結(jié)果類型為虛數(shù),如果一個(gè)操作數(shù)是實(shí)數(shù)而另一個(gè)虛數(shù),則如通常的算術(shù)轉(zhuǎn)換所指定的那樣):
| u | iv | u + iv |
---|---|---|---|
x | x ± u | x ± iv | (x ± u) ± iv |
iy | ±u + iy | i(y ± v) | ±u + i(y ± v) |
x + iy | (x ± u) + iy | x + i(y ± v) | (x ± u) + i(y ± v) |
// work in progress// note: take part of the c/language/conversion example
如果指針P
指向具有索引的數(shù)組的元素I
,則
P+N
并且N+P
是指向具有索引的相同數(shù)組的元素的指針I+N
P-N
是一個(gè)指向索引{tt | IN}}的相同數(shù)組元素的指針
只有在原始指針和結(jié)果指針都指向同一數(shù)組的元素或超過該數(shù)組的末尾時(shí),才會(huì)定義行為。請(qǐng)注意,當(dāng)p指向數(shù)組的第一個(gè)元素時(shí)執(zhí)行p-1是未定義的行為,并可能在某些平臺(tái)上失敗。
如果指針P1
指向一個(gè)數(shù)組中的索引I
(或者一個(gè)超過末尾的數(shù)組)P2
的元素并且指向具有索引的相同數(shù)組的元素J
(或者指向末尾的一個(gè)元素),那么
P1-P2
具有等于的值J-I
和類型ptrdiff_t
(這是一個(gè)有符號(hào)的整數(shù)類型,通常是可以聲明的最大對(duì)象的大小的一半)
The behavior is defined only if the result fits in ptrdiff_t
.
為了進(jìn)行指針運(yùn)算,指向不是任何數(shù)組元素的對(duì)象的指針將被視為指向大小為1的數(shù)組的第一個(gè)元素的指針。
// work in progressint n = 4, m = 3;int a[n][m]; // VLA of 4 VLAs of 3 ints eachint (*p)[m] = a; // p == &a[0] p = p + 1; // p == &a[1] (pointer arithmetic works with VLAs just the same)(*p)[2] = 99; // changes a[1][2]
二進(jìn)制乘法算術(shù)運(yùn)算符表達(dá)式具有這種形式。
lhs * rhs | (1) | |
---|---|---|
lhs / rhs | (2) | |
lhs % rhs | (3) |
1)乘法。lhs 和 rhs 必須有算術(shù)類型
2)division。lhs 和 rhs 必須有算術(shù)類型
3)余數(shù)。lhs 和 rhs 必須具有整數(shù)類型
首先,執(zhí)行通常的算術(shù)轉(zhuǎn)換。然后...
二進(jìn)制運(yùn)算符*在通常的算術(shù)定義之后執(zhí)行其操作數(shù)的乘法(在通常的算術(shù)轉(zhuǎn)換之后),除此之外。
如果一個(gè)操作數(shù)是 NaN,則結(jié)果是 NaN
如果無窮大乘以零,就會(huì)產(chǎn)生NaN并被FE_INVALID
提升
無窮乘以非零乘法給無窮(即使對(duì)于復(fù)雜的參數(shù))
因?yàn)樵贑中,任何具有至少一個(gè)無限部分的復(fù)數(shù)值作為無窮大,即使其另一部分是NaN,通常的算術(shù)規(guī)則也不適用于復(fù)數(shù)復(fù)數(shù)乘法。浮點(diǎn)操作數(shù)的其他組合遵循下表:
* | u | iv | u + iv |
---|---|---|---|
x | xu | i(xv) | (xu) + i(xv) |
iy | i(yu) | ?yv | (?yv) + i(yu) |
x + iy | (xu) + i(yu) | (?yv) + i(xv) | special rules |
除無限處理外,不允許復(fù)數(shù)乘法溢出中間結(jié)果,除非 #pragma STDC CX_LIMITED_RANGE
設(shè)置為ON
,在這種情況下,可以按照(x + iy)×(u + iv)=(xu-yv)+ i (yu + xv),因?yàn)槌绦騿T承擔(dān)限制操作數(shù)范圍和處理無窮大的責(zé)任。
盡管不允許不適當(dāng)?shù)囊绯觯珡?fù)雜的乘法可能會(huì)引發(fā)虛假的浮點(diǎn)異常(否則實(shí)現(xiàn)非溢出版本非常困難)。
除了那個(gè)之外,二元運(yùn)算符/第一操作數(shù)除以第二操作數(shù)(在通常的算術(shù)轉(zhuǎn)換之后)遵循通常的算術(shù)定義。
當(dāng)通常的算術(shù)轉(zhuǎn)換后的類型是一個(gè)整數(shù)類型時(shí),結(jié)果是代數(shù)商(不是分?jǐn)?shù)),在實(shí)現(xiàn)定義的方向上舍入(直到C99)向零截?cái)啵ㄒ驗(yàn)镃99)
如果一個(gè)操作數(shù)是NaN,則結(jié)果是NaN
如果第一個(gè)操作數(shù)是復(fù)數(shù)無窮大,第二個(gè)操作數(shù)是有限的,那么
/運(yùn)算符的結(jié)果是一個(gè)復(fù)雜的無窮大。
如果第一個(gè)操作數(shù)是有限的,第二個(gè)操作數(shù)是一個(gè)復(fù)數(shù)的無窮大,那么
/運(yùn)算符的結(jié)果是零。
因?yàn)樵贑中,任何具有至少一個(gè)無限部分的復(fù)數(shù)值作為無窮大,即使其另一部分是NaN,通常的算術(shù)規(guī)則也不適用于復(fù)數(shù)復(fù)數(shù)除法。浮點(diǎn)操作數(shù)的其他組合遵循下表:
/ | u | iv |
---|---|---|
x | x/u | i(?x/v) |
iy | i(y/u) | y/v |
x + iy | (x/u) + i(y/u) | (y/v) + i(?x/v) |
除無限處理外,復(fù)數(shù)除法不允許溢出中間結(jié)果,除非 #pragma STDC CX_LIMITED_RANGE
設(shè)置為ON
,在這種情況下,可以按照(x + iy)/(u + iv)=(xu + yv)+ i (宇-15)/(U2
+ v2
),因?yàn)槌绦騿T承擔(dān)限制操作數(shù)范圍和處理無窮大的責(zé)任。
盡管不允許不適當(dāng)?shù)囊绯?,?fù)雜的劃分可能會(huì)引發(fā)虛假的浮點(diǎn)異常(否則實(shí)現(xiàn)非溢出版本非常困難)。
如果第二個(gè)操作數(shù)為零,則行為是未定義的,但是如果支持 IEEE 浮點(diǎn)算術(shù)并且發(fā)生浮點(diǎn)除法,那么。
將非零數(shù)字除以±0.0會(huì)給出正確符號(hào)的無窮大,并將FE_DIVBYZERO
其升高
將0.0除0.0得到NaN并FE_INVALID
升高
二元運(yùn)算符%產(chǎn)生第一個(gè)操作數(shù)除以第二個(gè)操作數(shù)的其余部分(在通常的算術(shù)轉(zhuǎn)換后)。
余數(shù)的符號(hào)是這樣定義的,即如果商a/b
可以在結(jié)果類型中表示,那么(a/b)*b + a%b == a
。
如果第二個(gè)操作數(shù)為零,則行為未定義。
如果商a/b
不能在結(jié)果類型可表示,雙方的行為a/b
,并a%b
沒有定義(這意味著INT_MIN%-1
是未定義2的補(bǔ)數(shù)系統(tǒng))。
注意:余數(shù)運(yùn)算符不適用于浮點(diǎn)類型,庫(kù)函數(shù)fmod
提供該功能。
#include<stdio.h>#include <stdio.h>#include <complex.h>#include <math.h>int main(void){ // TODO simpler cases, take some from C++ double complex z = (1 + 0*I) * (INFINITY + I*INFINITY);// textbook formula would give// (1+i0)(∞+i∞) ? (1×∞ – 0×∞) + i(0×∞+1×∞) ? NaN + I*NaN// but C gives a complex infinity printf("%f + i*%f\n", creal(z), cimag(z)); // textbook formula would give// cexp(∞+iNaN) ? exp(∞)×(cis(NaN)) ? NaN + I*NaN// but C gives ±∞+i*nan double complex y = cexp(INFINITY + I*NAN); printf("%f + i*%f\n", creal(y), cimag(y)); }
可能的輸出:
inf + i*inf inf + i*nan
按位算術(shù)運(yùn)算符表達(dá)式具有這種形式。
~ rhs | (1) | |
---|---|---|
lhs & rhs | (2) | |
lhs | rhs | (3) | |
lhs ^ rhs | (4) |
1) bitwise NOT
2) bitwise AND
3) bitwise OR
4) bitwise XOR
其中
lhs, rhs | - | expressions of integer type |
---|
首先,運(yùn)營(yíng)商&,^和| 對(duì)兩個(gè)操作數(shù)執(zhí)行通常的算術(shù)轉(zhuǎn)換操作符?對(duì)其唯一的操作數(shù)執(zhí)行整數(shù)提升。
然后,相應(yīng)的二進(jìn)制邏輯運(yùn)算符按位進(jìn)行應(yīng)用; 也就是說,根據(jù)邏輯操作(NOT,AND,OR 或 XOR)將結(jié)果的每一位置1或清零,并將其應(yīng)用于操作數(shù)的相應(yīng)位。
注意:位運(yùn)算符通常用于操作位集和位掩碼。
注意:對(duì)于無符號(hào)類型(推廣后),表達(dá)式?E等于結(jié)果類型可表示的最大值減去E的原始值。
#include <stdio.h>#include <stdint.h>int main(void){ uint16_t mask = 0x00f0; uint32_t a = 0x12345678; printf("Value: %#x mask: %#x\n" "Setting bits: %#x\n" "Clearing bits: %#x\n" "Selecting bits: %#x\n", a,mask,(a|mask),(a&~mask),(a&mask));}
可能的輸出:
Value: 0x12345678 mask: 0xf0Setting bits: 0x123456f8Clearing bits: 0x12345608Selecting bits: 0x70
按位移運(yùn)算符表達(dá)式具有這種形式。
lhs << rhs | (1) | |
---|---|---|
lhs >> rhs | (2) |
1)左移 rhs 位
2)通過 rhs 位右移 lhs
其中
lhs, rhs | - | expressions of integer type |
---|
首先,對(duì)每個(gè)操作數(shù)單獨(dú)執(zhí)行整數(shù)升級(jí)(注意:這不同于其他二進(jìn)制算術(shù)運(yùn)算符,它們都執(zhí)行常規(guī)算術(shù)轉(zhuǎn)換)。結(jié)果的類型是促銷后的 lhs 類型。
對(duì)于無符號(hào)的 lhs,其值LHS << RHS
是 LHS * 2RHS 的值
返回類型的模數(shù)最大值減1加(即,執(zhí)行按位左移,并且丟棄從目標(biāo)類型移出的位)。對(duì)于有符號(hào)的 lhs,其值為LHS << RHS
LHS * 2RHS
如果它在升級(jí)類型的 lhs 中可表示,否則行為是未定義的。
對(duì)于無符號(hào)的 lhs 和帶有非負(fù)值的帶符號(hào)的 lhs,其值LHS >> RHS
是 LHS / 2RHS 的整數(shù)部分
對(duì)于負(fù)數(shù)LHS
,值LHS >> RHS
是實(shí)現(xiàn)定義的,在大多數(shù)實(shí)現(xiàn)中,這將執(zhí)行算術(shù)右移(以便結(jié)果保持負(fù)值)。因此,在大多數(shù)實(shí)現(xiàn)中,向右移位一個(gè)符號(hào)LHS
將使用原始符號(hào)位填充新的較高位(即,如果它是非負(fù)的則為0,如果是負(fù)的則為0)。
在任何情況下,如果 rhs 為負(fù)數(shù)或者大于或等于升級(jí)的 lhs 中的位數(shù),則行為是不確定的。
#include <stdio.h>enum {ONE=1, TWO=2};int main(void){ char c = 0x10; unsigned long long ulong_num = 0x123; printf("0x123 << 1 = %#llx\n" "0x123 << 63 = %#llx\n" // overflow truncates high bits for unsigned numbers "0x10 << 10 = %#x\n", // char is promoted to int ulong_num << 1, ulong_num << 63, c << 10); long long long_num = -1000; printf("-1000 >> 1 = %lld\n", long_num >> ONE); // implementation defined}
可能的輸出:
0x123 << 1 = 0x2460x123 << 63 = 0x80000000000000000x10 << 10 = 0x4000-1000 >> 1 = -500