操作符又稱為運(yùn)算符。作為運(yùn)算對象的變量或者常量稱為操作數(shù)。
操作符做左側(cè)的操作數(shù)稱為第一操作數(shù)或者左操作數(shù),操作符右邊的操作數(shù)稱為第二操作數(shù)或者右操作數(shù)。
操作符同時對兩個操作數(shù)進(jìn)行運(yùn)算的稱為雙目操作符,操作符只對一個操作數(shù)進(jìn)行運(yùn)算的稱為單目操作符。
在大家使用的電子計算機(jī)中所有的數(shù)據(jù)都是用ON/OFF信號(即1/0)來表示的。而我們比較用于理解的在日常接觸的是以10為基數(shù)的十進(jìn)制數(shù),而對計算機(jī)來說以2為基數(shù)的二進(jìn)制數(shù)則更易于理解。
基數(shù),在表示數(shù)值的時候,基數(shù)是進(jìn)位的基準(zhǔn)。基數(shù)為10的十進(jìn)制數(shù)哦,每逢10或10的倍數(shù)就進(jìn)位。
雖說對于硬件底層的程序而言,二進(jìn)制數(shù)會更加適宜,但是對于我們而言,將所有的數(shù)值都用二進(jìn)制數(shù)來表示可就是一件令人頭疼的事情了。二進(jìn)制雖然有很多優(yōu)點(diǎn),但是位數(shù)過多使得處理和閱讀不便也是不可忽略的缺點(diǎn),所以在寫法上還使用了相對書寫和便于閱讀的八進(jìn)制數(shù)和十六進(jìn)制數(shù)。
四種進(jìn)制十進(jìn)制
十進(jìn)制中,如果0~9這十個數(shù)字用完就進(jìn)位
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
10,11,12,13,14,15,16,17,18,19
20,21,22,23,24,25,26,27,28,29
八進(jìn)制
在八進(jìn)制中,如果0~7這八個數(shù)字用完就進(jìn)位
0, 1, 2, 3, 4, 5, 6, 7
10,11,12,13,14,15,16,17
20,21,22,23,24,25,26,27
在十六進(jìn)制中,十六個數(shù)分別為0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
,當(dāng)這十六個數(shù)用完時,進(jìn)位
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1F
在二進(jìn)制中,0和1用于表示所有的數(shù)據(jù),當(dāng)0和1用完進(jìn)位
00000000,00000001,00000010,00000011,00000100
上述五個二進(jìn)制數(shù)分別表示十進(jìn)制中:0,1,2,3,4
進(jìn)制轉(zhuǎn)換二進(jìn)制數(shù)規(guī)律:
對于一個十進(jìn)制數(shù)
如果為偶數(shù),那么這個數(shù)的二進(jìn)制數(shù)末尾數(shù)字為0
如果為奇數(shù),那么這個數(shù)的二進(jìn)制數(shù)末尾數(shù)字為1
(也就是說用一個十進(jìn)制數(shù)除以2做得到的余數(shù)就是末尾數(shù)字的值)
二進(jìn)制、八進(jìn)制、十六進(jìn)制 轉(zhuǎn) 十進(jìn)制數(shù)
十進(jìn)制 轉(zhuǎn) 二進(jìn)制、八進(jìn)制、十六進(jìn)制
轉(zhuǎn) 二進(jìn)制
將十進(jìn)制數(shù)57轉(zhuǎn)換為二進(jìn)制數(shù)的步驟如下:
57
/
2
=
28............1
28
/
2
=
14............0
14
/
2
=
7.............0
7
/
2
=
3..............1
3
/
2
=
1..............1
1
/
2
=
0..............1
轉(zhuǎn)
化
為
二
進(jìn)
制
結(jié)
果
為
:
111001
57/2=28............1\\ 28/2=14............0\\ 14/2=7.............0\\ 7 /2=3..............1\\ 3 /2=1..............1\\ 1 /2=0..............1\\ 轉(zhuǎn)化為二進(jìn)制結(jié)果為:111001
57/2=28............128/2=14............014/2=7.............07/2=3..............13/2=1..............11/2=0..............1轉(zhuǎn)化為二進(jìn)制結(jié)果為:111001
轉(zhuǎn) 八進(jìn)制
將十進(jìn)制數(shù)57轉(zhuǎn)換為八進(jìn)制數(shù)的步驟如下:
57
/
8
=
7............1
7
/
8
=
0............7
轉(zhuǎn)
化
為
八
進(jìn)
制
結(jié)
果
為
:
71
57/8=7............1\\ 7/8=0............7\\ 轉(zhuǎn)化為八進(jìn)制結(jié)果為:71
57/8=7............17/8=0............7轉(zhuǎn)化為八進(jìn)制結(jié)果為:71
轉(zhuǎn) 十六進(jìn)制
將十進(jìn)制數(shù)57轉(zhuǎn)換為十六進(jìn)制數(shù)的步驟如下:
57
/
16
=
3............9
3
/
16
=
0............3
轉(zhuǎn)
化
為
十
六
進(jìn)
制
結(jié)
果
為
:
39
57/16=3............9\\ 3/16=0............3\\ 轉(zhuǎn)化為十六進(jìn)制結(jié)果為:39
57/16=3............93/16=0............3轉(zhuǎn)化為十六進(jìn)制結(jié)果為:39
整數(shù)的二進(jìn)制表示形式其實(shí)有三種,分別為原碼、反碼、補(bǔ)碼。
原碼是我們平時所書寫的二進(jìn)制形式,例如把一個十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù),這個二進(jìn)制數(shù)就是原碼的形式。
而反碼和補(bǔ)碼,是通過原碼進(jìn)行轉(zhuǎn)換得到的。
而在內(nèi)存中,存儲的其實(shí)是補(bǔ)碼。所以對于對二進(jìn)制位進(jìn)行操作的操作符,本質(zhì)上都是對補(bǔ)碼進(jìn)行操作。
我們知道一個有符號數(shù)是分正負(fù)的,而在二進(jìn)制中,用最高位表示符號位,正數(shù)最高位為0,負(fù)數(shù)最高位為1。
對于一個有符號數(shù)來說
正數(shù):原碼、反碼、補(bǔ)碼相同。
負(fù)數(shù):原碼、反碼、補(bǔ)碼不同,原碼經(jīng)過計算可以得到反碼和補(bǔ)碼。
原碼反碼補(bǔ)碼計算
原碼:按照一個數(shù)的正負(fù),直接寫出其二進(jìn)制表示形式得到的就是原碼。
反碼:原碼的符號位不變,其余位全部按位取反,得到的就是反碼。
補(bǔ)碼:在反碼的基礎(chǔ)上加1,得到的就是補(bǔ)碼。
原碼求反碼計算流程
原碼 → 符 號 位 不 變 其 余 位 按 位 取 反 \xrightarrow[]{符號位不變其余位按位取反} 符號位不變其余位按位取反 ?反碼 → 反 碼 加 一 \xrightarrow[]{反碼加一} 反碼加一 ?補(bǔ)碼
反碼求原碼計算流程
操作符分類方法1:補(bǔ)碼 → 補(bǔ) 碼 減 一 \xrightarrow[]{補(bǔ)碼減一} 補(bǔ)碼減一 ?反碼 → 符 號 位 不 變 其 余 位 按 位 取 反 \xrightarrow[]{符號位不變其余位按位取反} 符號位不變其余位按位取反 ?原碼
方法2:補(bǔ)碼 → 符 號 位 不 變 其 余 位 按 位 取 反 \xrightarrow[]{符號位不變其余位按位取反} 符號位不變其余位按位取反 ?反碼 → 反 碼 加 一 \xrightarrow[]{反碼加一} 反碼加一 ?原碼
操作符 | 語法 | 求 |
---|---|---|
+ 操作符 | a + b | 和 |
- 操作符 | a - b | 差 |
* 乘法操作符 | a * b | 積 |
/ 除法操作符 | a / b | 商 |
% 取模(求余數(shù))操作符 | a % b | 余數(shù) |
9 / 2
的商為 49.0 / 2
的商為 4.500000(輸出為double類型)9 / 2
的余數(shù)為 1上面說過位操作符所操作的數(shù)是存儲在內(nèi)存中的補(bǔ)碼,所以位移操作符是對補(bǔ)碼進(jìn)行移位操作。
操作符 | 語法 | |
---|---|---|
<< 左移操作符 | a<< b | 將a左移b位,右邊空出的位用0填充 |
>>右移操作符 | a >>b | 將a右移b位 |
a<< b
會將a的所有位按位向左移動b位,并在右邊空出的位(低位)上補(bǔ)0,如果a為無符號整型,則a<< b
的運(yùn)算結(jié)果為
a
×
2
b
a\times2^b
a×2b。十進(jìn)制數(shù)在左移一位后,值會變成原本的十倍,例如196左移一位變?yōu)?960。二進(jìn)制也是一樣,在沒有溢出的情況下,左移一位值變?yōu)樵档?倍。
a >>b
會將a的所有位按位向右移動b位。如果a為無符號整型或者有符號整型的非負(fù)數(shù),則運(yùn)算結(jié)果為 a ÷ 2 b a\div2^b a÷2b所得到結(jié)果的整數(shù)部分。
如果a為有符號整型的負(fù)數(shù)形式,位移運(yùn)算的結(jié)果因編譯器的不同而會有所不同,在許多編譯器中會執(zhí)行邏輯位移或者算術(shù)位移,但是無論使用哪種方式都會降低程序的可移植性所以我們應(yīng)該或者說不要對負(fù)數(shù)進(jìn)行位移。
邏輯右移
邏輯右移不考慮符號位的情況是0還是1,所有的二進(jìn)制位都進(jìn)行位移,負(fù)整數(shù)右移時,符號位由1變?yōu)?,位移的結(jié)果為0或整數(shù)。
算術(shù)右移
算術(shù)右移,所有二進(jìn)制位進(jìn)行位移,用符號位來補(bǔ)空位,例如符號位為1,所有空位補(bǔ)1。
操作符 | 語法 | |
---|---|---|
& 按位與 | a & b | 計算a和b的邏輯與 |
| 按位或 | a | b | 計算a和b的邏輯或 |
^ 按位異或 | a ^ b | 計算a和b的邏輯異或 |
這些運(yùn)算符的操作數(shù)必須是整型數(shù)據(jù)類型或者枚舉類型。
這些運(yùn)算符會根據(jù)1為真0為假的運(yùn)算規(guī)則對操作數(shù)的各二進(jìn)制位進(jìn)行邏輯運(yùn)算。
int a = 3;
//正數(shù):原反補(bǔ)相同
//補(bǔ)碼:00000000000000000000000000000011
int b = -5;
//原碼:10000000000000000000000000000101
//反碼:11111111111111111111111111111010
//補(bǔ)碼:11111111111111111111111111111011
int c = a & b;
//a-補(bǔ)碼:00000000000000000000000000000011
//b-補(bǔ)碼:11111111111111111111111111111011
// a & b:00000000000000000000000000000011
int c = a | b;
//a-補(bǔ)碼:00000000000000000000000000000011
//b-補(bǔ)碼:11111111111111111111111111111011
// a | b:11111111111111111111111111111011
int c = a | b;
//a-補(bǔ)碼:00000000000000000000000000000011
//b-補(bǔ)碼:11111111111111111111111111111011
// a ^ b:11111111111111111111111111111000
賦值操作符操作符 | 語法 | |
---|---|---|
= 賦值操作符 | a = b | 把b的值賦值給a |
利用賦值操作符,你可以將你之前不滿意的值修改為你滿意的值(例如你的工資)
復(fù)合賦值符操作符 | 語法 | |
---|---|---|
+= 加法賦值 | a += b | a = a + b |
-= 減法賦值 | a -= b | a = a - b |
*= 乘法賦值 | a *= b | a = a * b |
/= 除法賦值 | a /= b | a = a / b |
%= 取模賦值 | a %= b | a = a % b |
<<= 左移賦值 | a >>= b | a = a >>b |
>>= 右移賦值 | a<<= b | a = a<< b |
&= 位邏輯與賦值 | a &= b | a = a & b |
|= 位邏輯或賦值 | a |= b | a = a | b |
^= 位邏輯異或賦值 | a ^= b | a = a ^ b |
操作符 | 語法 | |
---|---|---|
! 邏輯反 | !a | 當(dāng)a本身為0時,!a值為1, 當(dāng)a本身為1時,!a值為0 |
- 負(fù)值 | -a | a值為正數(shù)時,-a值為負(fù)數(shù) |
+ 正值 | +a | |
& 取地址 | &a | 取a的地址 |
sizeof 求類型長度 | sizeof(a) | 求a(對象、常量、類型名等)的長度 |
~ 按位取反 | ~a | 對一個數(shù)的二進(jìn)制位按位取反 |
– 自減1 | a–/–a | –a,前置–,先自減1再使用 a–,后置–,先使用再自減1 |
++ 自加1 | a++/++a | ++a,前置++,先自加1再使用 a++,后置++,先使用再自加1 |
* 間接訪問操作符 | *a | 又稱為解引用操作符 |
()強(qiáng)制類型轉(zhuǎn)換 | (類型)a | 將一個變量的或者常量的類型,強(qiáng)制類型轉(zhuǎn)換為括號內(nèi)的類型 |
操作符 | 語法 | |
---|---|---|
> | a >b | 判斷a是否大于b,若a大于b返回1,若a不大于b返回0 |
>= | a >= b | 判斷a是否大于等于b,若a大于等于b返回1,若a小于b返回0 |
< | a< b | 判斷a是否小于b,若a小于b返回1,若a不小于b返回0 |
<= | a<= b | 判斷a是否小于等于b,若a小于等于b返回1,若大于b返回0 |
!= | a != b | 判斷a是否不等于b,若a不等于b返回1,若a等于b返回0 |
== | a == b | 判斷a是否等于b,若a等于b返回1,若a不等于b返回0 |
邏輯操作符要注意區(qū)分=和== 一個等號為賦值兩個等號為判斷相等
操作符 | 語法 | |
---|---|---|
&& 邏輯與 | a && b | 如果a和b都不為0,則表達(dá)式的結(jié)果為1;如果a和b其中一個為0則表達(dá)式結(jié)果為0 |
|| 邏輯或 | a || b | 如果a和b中有一個不為0,則表達(dá)式的結(jié)果為1;如果a和b都為0,則表達(dá)式結(jié)果為0 |
C語言中0表示假,非0表示真
要注意區(qū)分
邏輯與 和 按位與
邏輯或 和 按位或
true
,假為false
看一段C語言源代碼
#define bool _Bool
#define false 0
#define true 1
從上述代碼我們可以知道,布爾類型的本質(zhì)還是0和1,在編寫代碼時,使用bool
和_bool
都是允許的。
&&
邏輯與操作符,在左操作數(shù)的結(jié)果為0時,操作符右邊操作數(shù)不再進(jìn)行計算。||
邏輯或操作符,在左操作數(shù)的結(jié)果不為0時,不再對右邊的操作數(shù)進(jìn)行計算。操作符 | 語法 | |
---|---|---|
exp1 ? exp2 : exp3 | a ? b : c | 計算表達(dá)式a,若a不為0,則結(jié)果為表達(dá)式b的結(jié)果;若a為0,則結(jié)果為表達(dá)式c的結(jié)果 |
操作符 | 語法 | |
---|---|---|
exp1,exp2,exp3,…,expN | a,b,c | 從左向右依次執(zhí)行,整個逗號表達(dá)式的結(jié)果就是最后一個表達(dá)式expN的計算結(jié)果 |
操作符 | 語法 | |
---|---|---|
[ ] | arr[a] | 訪問數(shù)組arr中下標(biāo)為a的元素 |
操作符 | 語法 | |
---|---|---|
( ) | strlen(“abcdef”) | 調(diào)用strlen函數(shù),求abcdef的字符串長度 |
操作符 | 語法 | |
---|---|---|
. | a . b | 表示結(jié)構(gòu)體a中的成員b;a為對象名或者結(jié)構(gòu)體名,b為成員名。 |
-> | a ->b | 用指針訪問結(jié)構(gòu)體a中的成員b;a為結(jié)構(gòu)體指針,b為成員名 |
(*p).m
可以簡寫為p->m
。
表達(dá)式求值
.
運(yùn)算符和->
運(yùn)算符統(tǒng)稱為訪問運(yùn)算符。
表達(dá)式求值的順序一般是由操作符的優(yōu)先級和結(jié)合性決定的。
隱式類型轉(zhuǎn)換(整型提升)在C語言整型算術(shù)運(yùn)算中,通常至少以整型類型的精度進(jìn)行計算。為了獲得這一精度,表達(dá)式中的字符或者短整型操作數(shù)會在使用之前轉(zhuǎn)換為普通整型,這種轉(zhuǎn)換稱為整型提升。
當(dāng)然,如果在同時存在int型和unsigned int型的表達(dá)式中,如果int型無法表示出原數(shù)據(jù)類型的所有數(shù)值,就將值轉(zhuǎn)換為unsigned int型。
整型提升 不會改變符號和數(shù)值,char類型是否作為符號類型來處理,需要由編譯器決定,不同的編譯器所運(yùn)算標(biāo)準(zhǔn)不同。
#includeint main()
{
//int類型內(nèi)存中占位為4個字節(jié),32個比特位
//char類型內(nèi)存中占位為1個字節(jié),8個比特位
char a = 3;
//3在內(nèi)存中的補(bǔ)碼為:00000000000000000000000000000011
//把一個int類型的3存放在char類型的a中需要進(jìn)行截斷
//00000011 -a
char b = 127;
//127在內(nèi)存中的補(bǔ)碼為:00000000000000000000000001111111
//01111111 -b
char c = a + b;
//表達(dá)式中的字符或轉(zhuǎn)整型在使用之前需要轉(zhuǎn)換為普通整型——這種轉(zhuǎn)換稱為整型提升
//在vs2019中默認(rèn)char類型為signed char也就是有符號字符類型
//對于有符號類型的整型提升,符號位為什么(0/1),整型提升時的空位就補(bǔ)什么
//00000000000000000000000000000011 -a //符號位為0,空位補(bǔ)0
//00000000000000000000000001111111 -b
//00000000000000000000000010000010 -a+b
//把a(bǔ)+b之后得到的存儲在char類型的c中需要進(jìn)行截斷
//10000010 -c
printf("%d\n", c);
// %d 打印一個十進(jìn)制的整型
//c為一個有符號char類型,所以需要進(jìn)行整型提升
//10000010 -c 符號位為1 整型提升空位補(bǔ)1
//11111111111111111111111110000010 -補(bǔ)碼
//內(nèi)存中存儲的是二進(jìn)制補(bǔ)碼形式,打印顯示出來的為原碼表示的十進(jìn)制值
//11111111111111111111111110000001
//10000000000000000000000001111110 -原碼
return 0;
}
總結(jié):
算術(shù)轉(zhuǎn)換在表達(dá)式進(jìn)行運(yùn)算之前,編譯器會自動為表達(dá)式中的char類型和short類型操作數(shù)進(jìn)行整型提升,然后在進(jìn)行運(yùn)算。
當(dāng)把一個較大類型存儲在一個較小類型中,需要進(jìn)行截斷
不同的編譯器對于char類型是否有符號是不同的
如果一個雙目操作符,甚至多目操作符的幾個操作數(shù)屬于不同的數(shù)據(jù)類型,那么編譯器會對其做數(shù)據(jù)類型轉(zhuǎn)換。數(shù)據(jù)類型轉(zhuǎn)換的目的是為了確定通用數(shù)據(jù)類型,否則不同的數(shù)據(jù)類型操作數(shù)不能將進(jìn)行運(yùn)算。這一過程稱為普通算術(shù)類型轉(zhuǎn)換。
類型 | 排名 |
---|---|
long double | 1 |
double | 2 |
float | 3 |
unsigned long int | 4 |
long int | 5 |
unsigned int | 6 |
int | 7 |
操作符屬性上述表格中的類型,如果同時出現(xiàn)在一個操作符的操作數(shù)中,在進(jìn)行算術(shù)類型轉(zhuǎn)換時,通常為排名靠后的向排名靠前的類型轉(zhuǎn)換。
但是也要注意,轉(zhuǎn)換需要合理,不然會造成精度的缺失,例如一個浮點(diǎn)型數(shù)轉(zhuǎn)換為int型,小數(shù)點(diǎn)后面的數(shù)會丟失,造成精度丟失。
復(fù)雜表達(dá)式的求值具有三個影響的因素:
- 操作符的優(yōu)先級
- 操作符的結(jié)合性
- 是否控制求值順序
兩個相鄰的操作符,誰的優(yōu)先級高先執(zhí)行誰。
優(yōu)先級相同,取決于結(jié)合性。
注意:如果我們寫出的表達(dá)式,不能通過操作符的屬性確定其唯一的計算路徑,那么這個表達(dá)式就是存在問題的?。?!
t | 3 |
| unsigned long int | 4 |
| long int | 5 |
| unsigned int | 6 |
| int | 7 |
操作符屬性上述表格中的類型,如果同時出現(xiàn)在一個操作符的操作數(shù)中,在進(jìn)行算術(shù)類型轉(zhuǎn)換時,通常為排名靠后的向排名靠前的類型轉(zhuǎn)換。
但是也要注意,轉(zhuǎn)換需要合理,不然會造成精度的缺失,例如一個浮點(diǎn)型數(shù)轉(zhuǎn)換為int型,小數(shù)點(diǎn)后面的數(shù)會丟失,造成精度丟失。
復(fù)雜表達(dá)式的求值具有三個影響的因素:
- 操作符的優(yōu)先級
- 操作符的結(jié)合性
- 是否控制求值順序
兩個相鄰的操作符,誰的優(yōu)先級高先執(zhí)行誰。
優(yōu)先級相同,取決于結(jié)合性。
[外鏈圖片轉(zhuǎn)存中…(img-xsiyNEIi-1669379888954)]
注意:如果我們寫出的表達(dá)式,不能通過操作符的屬性確定其唯一的計算路徑,那么這個表達(dá)式就是存在問題的?。?!
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧