溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C語(yǔ)言中操作符的介紹及用法

發(fā)布時(shí)間:2021-08-03 18:09:30 來(lái)源:億速云 閱讀:123 作者:chen 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要講解了“C語(yǔ)言中操作符的介紹及用法”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“C語(yǔ)言中操作符的介紹及用法”吧!

目錄
  • 操作符

    • 分類

    • 算術(shù)操作符

    • 移位操作符

    • 整數(shù)存儲(chǔ)規(guī)則

    • 左右移位規(guī)則

    • 賦值操作符

    • 單目操作符

    • 取地址操作符& 解引用操作符*

    • 類型長(zhǎng)度操作符sizeof

    • 按位取反操作符~

    • ++ -- 操作符

    • 強(qiáng)制類型轉(zhuǎn)換操作符(type)

    • 關(guān)系操作符=

    • 邏輯操作符

    • 短路運(yùn)算

    • 條件操作符

    • 逗號(hào)表達(dá)式

    • 下標(biāo)引用、函數(shù)調(diào)用和結(jié)構(gòu)成員

    • 下標(biāo)引用操作符[]

    • 函數(shù)調(diào)用操作符()

    • 結(jié)構(gòu)成員操作符. ->

    • 結(jié)構(gòu)體定義

    • 結(jié)構(gòu)體使用

    • 結(jié)構(gòu)體地址

    • 表達(dá)式求值

      • 隱式類型轉(zhuǎn)換

      • 整型提升

    • 如何整型提升

      • 有符號(hào)數(shù)

        • 無(wú)符號(hào)數(shù)

          • 算術(shù)轉(zhuǎn)換

            • 操作符的屬性

            • 總結(jié)

              操作符

              分類

              算術(shù)操作符

              移位操作符

              位操作符

              賦值操作符

              單目操作符

              關(guān)系操作符

              邏輯操作符

              條件操作符

              逗號(hào)表達(dá)式

              下標(biāo)引用、函數(shù)調(diào)用和結(jié)構(gòu)成員

              算術(shù)操作符

              + - * / %

              //1.
              int ret = 9 / 2;
              printf("%d", ret);//4
              //2.
              double ret2 = 9 / 2;
              printf("%lf", ret2);//4.000000
              //3.
              double ret3 = 9 / 2.0;
              printf("%lf", ret3);//4.500000

              從這兩個(gè)對(duì)比可以看出,不是存儲(chǔ)的問(wèn)題,而是計(jì)算機(jī)里9/2就是等于4,怎么存都是4。

              要想得到正確結(jié)果,則要改成9.0/2或者9/2.0。

              / 的兩個(gè)操作數(shù)都為整數(shù)時(shí),執(zhí)行整數(shù)除法,只要有浮點(diǎn)數(shù)就執(zhí)行浮點(diǎn)數(shù)除法。% 的兩個(gè)操作數(shù)必須為整數(shù),所得結(jié)果的范圍在 [ 0 , 除 數(shù) ? 1 ] [0, 除數(shù)-1] [0,除數(shù)?1] 之間。

              接下來(lái)的移位操作符和位操作符都是較為復(fù)雜的,涉及到二進(jìn)制位。

              移位操作符

              << //左移操作符
              >> //右移操作符

              整數(shù)存儲(chǔ)規(guī)則

              移位操作符移動(dòng)的是二進(jìn)制位,整數(shù)在內(nèi)存中存儲(chǔ)的是二進(jìn)制補(bǔ)碼,移位操作的也是內(nèi)存中的補(bǔ)碼。

              整數(shù)在內(nèi)存中的存儲(chǔ):

              • 正數(shù): 原

                • 碼反碼補(bǔ)碼相同

              • 負(fù)數(shù):

                • 原碼:二進(jìn)制序列

                • 反碼:原碼符號(hào)位不變,其他位按位取反

                • 補(bǔ)碼:反碼 + 1

              左右移位規(guī)則

              知道二進(jìn)制位如何轉(zhuǎn)化后,我們?cè)賮?lái)看移位操作符的移動(dòng)規(guī)則。

              1.左移操作符

              左邊舍棄,右邊補(bǔ)0

              C語(yǔ)言中操作符的介紹及用法

              int a = 5;
              int b = a << 1;

              a<<1的意思就是a的補(bǔ)碼向左移動(dòng)一位,正數(shù)的原反補(bǔ)相同,所以得補(bǔ)碼為00000000 00000000 00000000 00000101 ,向左移動(dòng)一位得00000000 00000000 00000000 00001010,換算一下就可得到10。

              此時(shí)a的值還是5,可以類比b=a+1,a并不會(huì)發(fā)生變化。

              int c = -1;
              int d = c << 1;

              先寫出 -1的原碼,再取反加一得補(bǔ)碼,補(bǔ)碼向左移動(dòng)一位,然后將得到的補(bǔ)碼按相同規(guī)則換算成原碼,就可以得到 -2了。

              10000000 00000000 00000000 00000001 - -1的原碼
              11111111 11111111 11111111 11111110 - -1的反碼
              11111111 11111111 11111111 11111111 - -1的補(bǔ)碼

              11111111 11111111 11111111 11111110 - -1<<1的補(bǔ)碼
              11111111 11111111 11111111 11111101 - 反碼
              10000000 00000000 00000000 00000010 - 原碼 = -2

              2.右移操作符

              右移規(guī)則分兩種,一種是邏輯右移一種是算術(shù)右移。但絕大多數(shù)編譯器都是采用算術(shù)右移。

              算術(shù)右移:左邊補(bǔ)原符號(hào)位,右邊舍棄

              邏輯右移:左邊補(bǔ)0,右邊舍棄

              int a = -1;
              printf("%d\n", a >> 1);
              //10000000 00000000 00000000 00000001 - 原碼
              //11111111 11111111 11111111 11111110 - 反碼 
              //11111111 11111111 11111111 11111111 - 補(bǔ)碼
              //11111111 11111111 11111111 11111111 - 補(bǔ)碼

              邏輯右移會(huì)把負(fù)數(shù)搞成整數(shù),所以算術(shù)右移顯得更正確一些。

              值得一提的是,-1的補(bǔ)碼右移一位后仍是-1。

              補(bǔ)充:

              不難發(fā)現(xiàn)左移使數(shù)據(jù)變大,右移使數(shù)據(jù)變小,左移就是數(shù)據(jù) × 2 ×2 ×2,右移即數(shù)據(jù) ÷ 2 ÷2 ÷2 。左移右移操作數(shù)必須為整數(shù)。移位操作符不可移動(dòng)負(fù)數(shù)位,即1>>-1,標(biāo)準(zhǔn)未定義行為。

              位操作符

              & //按位與
              | //按位或
              ^ //按位異或

              同樣位操作符也是按二進(jìn)制位。

              運(yùn)算規(guī)則

              按位與 &

              全1則1,有0則0

              按位或 |

              有1則1,全0則0

              按位異或 ^

              相同為0,相異為1

              通過(guò)運(yùn)算規(guī)則可以看出,按位與和按位或和邏輯與、邏輯或還是有異曲同工之妙的。

              int a = 3;
              int b = -2;
              int c = a & b;
              //1.求a的補(bǔ)碼
              100000000 000000000 000000000 000000010 - -2的原碼
              111111111 111111111 111111111 111111101 - -2的反碼
              111111111 111111111 111111111 111111110 - -2的補(bǔ)碼
              //2.求b的補(bǔ)碼   
              000000000 000000000 000000000 000000011 -  3的原反補(bǔ)相同!!
              //3.求a & b 
              111111111 111111111 111111111 111111110 - -2的補(bǔ)碼
              000000000 000000000 000000000 000000011 -  3的補(bǔ)碼
              000000000 000000000 000000000 000000010 - 所得數(shù)的補(bǔ)碼!! (全1為1,有0則0) 
              //4.轉(zhuǎn)化為原碼
              000000000 000000000 000000000 000000010 - 正數(shù)的原反補(bǔ)相同

              計(jì)算方法

              • 求兩操作數(shù)的補(bǔ)碼

              • 計(jì)算按位與、或、異或的結(jié)果

              • 將所得補(bǔ)碼轉(zhuǎn)換成原碼

              將a和b的補(bǔ)碼求出來(lái),然后再按位與、或,得到所得數(shù)的補(bǔ)碼,再轉(zhuǎn)換成原碼。這幾步很繞人,前往別被帶溝里了。其他兩個(gè)除了運(yùn)算規(guī)則不一樣外,其他都一樣。

              注意

              1.整數(shù)的原反補(bǔ)相同,可別照負(fù)數(shù)的規(guī)范求。

              2.按位與、按位或的結(jié)果同樣是補(bǔ)碼,最后還需轉(zhuǎn)換成原碼。

              例題

              不創(chuàng)建臨時(shí)變量,實(shí)現(xiàn)兩數(shù)交換。

              int a = 10;
              int b = 20;
              printf("a=%d,b=%d\n", a, b);
              //1.
              a = a + b;
              b = a - b;//(a+b)-b = a
              a = a - b;//(a+b)-a = b
              printf("a=%d,b=%d\n", a, b);
              //溢出風(fēng)險(xiǎn)

              //2.
              a = a ^ b;
              b = a ^ b;//(a ^ b) ^ b = a
              a = a ^ b;//(a ^ b) ^ a = b
              //可讀性差,只支持正數(shù)

              a^b的值再和a異或,則得到b;a^b的值再和b異或,則得到a。a ^ a = 0 a ^ 0 = a(a ^ a) ^ b = b (a ^ b) ^ a = b ,由此也可以說(shuō)異或支持交換律

              用處

              給出一個(gè)正整數(shù),想知道其(如果是負(fù)數(shù)的話,就是補(bǔ)碼)二進(jìn)制位最低位是0是1,怎么辦?

              將這個(gè)正整數(shù)按位與1,如果所得結(jié)果為1則最低位為1,反之則為0。如:

              int a = 15;
              int b = a & 1;
              00000000 00000000 00000000 00001111 - 15原反補(bǔ)相同
              00000000 00000000 00000000 00000001 - 1
              00000000 00000000 00000000 00000001 - b=1原反補(bǔ)相同

              從這個(gè)例子可以看出某個(gè)正數(shù)&1,所得結(jié)果為1則最低位為1,反之則為0。如果搭配上>>右移操作符,可以得到每一位的數(shù)字。 如:

              int num = 15;
              int count = 0;
              for (int i = 0; i < 32; i++)
              {
                  if (((num >> i) & 1) == 1){
                      count++;
                  }
              }
              printf("%d\n", count);

              賦值操作符

              =
              //復(fù)合賦值符
              += -= *= /= %= >>= <<=

              賦值操作符沒(méi)什么講頭,我們來(lái)看看一些奇葩的東西。

              int a = 10;
              int x = 0;
              int y = 20;
              a = x = y+1;//連續(xù)賦值

              如何理解這個(gè)連續(xù)賦值呢?

              先是把y+1賦值給了x,再把表達(dá)式x=y+1的值賦值給了a 。

              單目操作符

              ! //邏輯反操作
              - //取負(fù)
              + //取正
              & //取地址
              sizeof //操作數(shù)的類型長(zhǎng)度
              ~ //按位取反
              -- //前后置——
              ++ //前后置++
              * //解引用操作符
              (type) //強(qiáng)制類型轉(zhuǎn)換

              邏輯反操作!

              非零即為真,零為假,默認(rèn)規(guī)定 !0=1

              取地址操作符& 解引用操作符*

              int a = 10;
              int* p = &a;//* - 說(shuō)明p為指針變量 ,& - 說(shuō)明p中存儲(chǔ)的是a的地址
              *p = 20;//解引用訪問(wèn)其存儲(chǔ)的地址中的內(nèi)容
              printf("%d\n", *p);

              數(shù)組名作首元素地址問(wèn)題

              int arr[10] = { 0 };
              //1.
              printf("%p\n", arr + 1);
              //2.
              printf("%p\n", &arr[0] + 1);
              //3.
              printf("%p\n", &arr + 1);

              arr和arr[0]都是首元素的地址,&arr是整個(gè)數(shù)組的地址,打印出來(lái)都是一樣的。但是當(dāng)他們都+1區(qū)別就出現(xiàn)了,前兩個(gè)加1都是第二個(gè)元素的地址,而&arr加1就跳過(guò)了整個(gè)數(shù)組的地址。

              拓寬一點(diǎn),*p放在=左邊就是一塊空間,而放在=右邊就是一個(gè)值。

              //1.
              int b = *p;//這里*p代表值
              //2.
              *p = b;//這里*p就代表一塊空間用以存放值

              任何一個(gè)變量都可以這樣理解,放在=的左邊代表一塊空間a = 10;,就是左值。放在=右邊就是代表值p = a;,即右值。

              類型長(zhǎng)度操作符sizeof

              sizeof計(jì)算變量或類型所占內(nèi)存空間的大小,與其內(nèi)存中存放的數(shù)據(jù)是什么無(wú)關(guān)。

              //1.
              printf("%d\n", sizeof arr);
              //2.
              printf("%d\n", strlen(arr));

              sizeof strlen() 二者的區(qū)別

              sizeof 是計(jì)算所占空間的操作符,不關(guān)心存放的數(shù)據(jù)strlen() 是計(jì)算字符串長(zhǎng)度的函數(shù),關(guān)注存放的數(shù)據(jù)中的\0 前的字符個(gè)數(shù)

              sizeof 后面的()是表達(dá)式的括號(hào),而不是函數(shù)調(diào)用操作符,正因sizeof 是操作符,所以可以省略。

              例題:

              int a = 5;
              short s = 10;
              printf("%d\n", sizeof(s = a + 2));//?
              printf("%d\n", s);//?

              把int型數(shù)據(jù)a+2賦值給short型數(shù)據(jù)s,會(huì)發(fā)生整型截?cái)?,還是short 型的數(shù)據(jù)。

              sizeof 內(nèi)部的表達(dá)式是不參與運(yùn)算的,所以s原來(lái)是多少現(xiàn)在還是多少。原因:sizeof內(nèi)部的運(yùn)算時(shí)再預(yù)編譯時(shí)期處理的,在程序執(zhí)行期間早已將內(nèi)部的表達(dá)式替換成了數(shù)字。

              按位取反操作符~

              將其二進(jìn)制位所有位統(tǒng)統(tǒng)取反。

              例題

              如何將二進(jìn)制位指定一位1修改為0,0修改為1?

              int a = 13;
              //00000000 00000000 00000000 00001101 - 13
              //00000000 00000000 00000000 00000010 - 1<<1
              //00000000 00000000 00000000 00001111 - 15
              int b = a | (1<<1);
              printf("%d\n", b);
              //00000000 00000000 00000000 00001111 - 15
              //11111111 11111111 11111111 11111101 - ~(1<<1)
              //00000000 00000000 00000000 00001101 - 13
              int c = b & (~(1 << 1));
              printf("%d\n", c);

              該二進(jìn)制位為0想改為1,則按位或上這么一個(gè)數(shù)字..00100..。該二進(jìn)制位為1想改為0,則按位與上這么一個(gè)數(shù)字..11011..

              ++ -- 操作符

              前置++ --是先使用在修改,后置++ --先修改再使用。

              int a = 0;
              printf("%d\n", a);
              int b = a++;
              printf("%d\n", b);
              int c = --a;
              printf("%d\n", c);

              ++ --這樣使用就可以了,不要去追求一些沒(méi)用的復(fù)雜使用,沒(méi)人會(huì)去那么用的,寫代碼的目的并不是不讓人看懂。如:

              int a = 0;
              int b=(++a)+(a++)+(a++);

              這樣的代碼再不同的編譯器上會(huì)跑出不同的結(jié)果,沒(méi)必要在這個(gè)上浪費(fèi)時(shí)間。

              強(qiáng)制類型轉(zhuǎn)換操作符(type)

              int a = (int)3.14;

              例題

              void test1(int arr[]){
              	printf("%d\n", sizeof(arr));//(2)
              }
              void test2(char ch[]){
              	printf("%d\n", sizeof(ch));//(4)
              }
              int main(){
              	int arr[10] = { 0 };
              	char ch[10] = { 0 };
              	printf("%d\n", sizeof(arr));//(1)
              	printf("%d\n", sizeof(ch));//(3)
              	test1(arr);
              	test2(ch);
              	return 0;
              }
              (1) 和 (3) 沒(méi)問(wèn)題,數(shù)組名單獨(dú)放在sizeof內(nèi),計(jì)算的是整個(gè)數(shù)組的大小,分別是40和10。(2) 和 (4) 是數(shù)組名作函數(shù)參數(shù)。別看表面上是用數(shù)組接收,其實(shí)是用指針接收的,計(jì)算的都是指針的大小。數(shù)組名作函數(shù)參數(shù),沒(méi)有可能將數(shù)組整個(gè)傳參過(guò)去,編譯器自動(dòng)將其降級(jí)優(yōu)化為指向元素首地址的指針。

              關(guān)系操作符=

              > >= < <= != ==

              ==和=不一樣,如果寫錯(cuò)就成賦值了。

              邏輯操作符

              && //邏輯與
              || //邏輯或

              邏輯操作符只關(guān)注真假,邏輯與 && 就是并且,邏輯或 || 就是或者。

              邏輯與 && 兩邊操作數(shù)都為真,整個(gè)條件才為真,邏輯或 ||兩邊操作數(shù)有一個(gè)是真,則整個(gè)條件就為真。

              例題

              int main()
              {
              int i = 0,a=0,b=2,c =3,d=4;
              i = a++ && ++b && d++;
              i = a++||++b||d++;
              printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
              return 0;
              }

              短路運(yùn)算

              1.邏輯與 &&,當(dāng)左邊的表達(dá)式為假時(shí),整個(gè)條件為假,不再進(jìn)行運(yùn)算。

              2.邏輯或 +,當(dāng)左邊的表達(dá)式為真時(shí),整個(gè)條件為真,不再進(jìn)行運(yùn)算。

              i = a++ && ++b && d++,第一步a++=0為假,則整個(gè)表達(dá)式為假,i=0;i = a++||++b||d++,第二步a++為真,整個(gè)表達(dá)式為真,后面的表達(dá)式也不進(jìn)行運(yùn)算了。

              條件操作符

              exp1 ? exp2 : exp3

              表達(dá)式exp1的結(jié)果為真,執(zhí)行exp2并將exp2的結(jié)果作為整個(gè)表達(dá)式的結(jié)果,反之,則執(zhí)行exp3并將其賦值給整個(gè)表達(dá)式。

              逗號(hào)表達(dá)式

              exp1, exp2, exp3,...,expN

              從左向右依次計(jì)算,整個(gè)表達(dá)式的結(jié)果為最后一個(gè)表達(dá)式的結(jié)果。

              那既然這樣,為什么我們還要計(jì)算前面的表達(dá)式呢,直接算最后一個(gè)不就好了嗎?

              前面的表達(dá)式可能會(huì)影響到最后一個(gè)表達(dá)式的值。如:

              int a = 1,b = 2;
              int c = (a>b, a=b+10, a, b=a+1);

              下標(biāo)引用、函數(shù)調(diào)用和結(jié)構(gòu)成員

                 []   ()   .   ->

              下標(biāo)引用操作符[]

              C語(yǔ)言中操作符的介紹及用法

              arr+i即為數(shù)組中下標(biāo)為i的元素的地址。

              []是一個(gè)操作符,它的兩個(gè)操作數(shù)分別為數(shù)組名和下標(biāo),缺一不可。對(duì)于arr[i]可理解為*(arr+i),既然如此我們就可寫出:

              arr[i] <=> *(arr+i) <=> *(i+arr) <=> i[arr]
              int arr[10] = { 0 };
              for (int i = 0; i < 10; i++){
                  printf("%p --- %p\n", &i[arr], i+arr);
              }

              這就體現(xiàn)出了[]是個(gè)操作符,這樣的寫法語(yǔ)法是支持的。

              函數(shù)調(diào)用操作符()

              printf("%u\n", strlen("abc"));

              這里printf和strlen函數(shù)都必須帶上(),不傳參也要帶上,不然就錯(cuò)。

              對(duì)于函數(shù)調(diào)用操作符(),可以有一個(gè)或者兩個(gè)操作數(shù)都可以。

              結(jié)構(gòu)成員操作符. ->

              . 結(jié)構(gòu)體.成員名

              -> 結(jié)構(gòu)體指針 -> 成員名

              結(jié)構(gòu)體用于描述一個(gè)復(fù)雜的對(duì)象。

              結(jié)構(gòu)體定義

              struct Book{
              	char name[50];
              	char id[15];
              	float price;
              };

              結(jié)構(gòu)體使用

              Print(struct Book b1){
              	printf("書(shū)名為:%s\n", b1.name);
              	printf("價(jià)格為:%f\n", b1.price);
              	printf("書(shū)號(hào)為:%s\n", b1.id);
              }
              int main(){
              	struct Book b1 = { "譚浩強(qiáng)C語(yǔ)言程序設(shè)計(jì)",55.5f,"2020322222" };
              	Print(b1);
              	return 0;
              }

              使用結(jié)構(gòu)體類型struct Book創(chuàng)建了一個(gè)結(jié)構(gòu)體類型的變量b,b中成員有三個(gè)name、id和price。

              我們還可以后續(xù)去修改價(jià)格,如:

              b1.price = 100.0f;

              那我們能不能把書(shū)名或者書(shū)號(hào)都給改了呢?

              b1.name = "數(shù)據(jù)結(jié)構(gòu)";

              當(dāng)然是不行的,我們可以看得出,書(shū)名name和書(shū)號(hào)id都是通過(guò)數(shù)組創(chuàng)建的。對(duì)于他們來(lái)說(shuō)b1.name是數(shù)組的首地址。怎么能對(duì)地址賦值呢。

              那既然是地址的話,我們對(duì)地址進(jìn)行解引用,不就可以訪問(wèn)數(shù)組元素了嘛~,我們?cè)僭囈幌隆?/p>

              *(b1.name) = "數(shù)據(jù)結(jié)構(gòu)";

              當(dāng)然,仍然是不對(duì)的,會(huì)顯示亂碼。

              那如何結(jié)構(gòu)體變量的數(shù)組成員呢,答案是使用庫(kù)函數(shù)strcpy對(duì)字符串賦值

              strcpy(b1.name, "數(shù)據(jù)結(jié)構(gòu)");

              結(jié)構(gòu)體地址

              將變量地址傳過(guò)去,如何使用呢?

              1.(*結(jié)構(gòu)體指針).成員名

              Print2(struct Book* pb){
              	printf("書(shū)名為:%s\n", (*pb).name);
              	printf("價(jià)格為:%f\n", (*pb).price);
              	printf("書(shū)號(hào)為:%s\n", (*pb).id);
              }

              2.結(jié)構(gòu)體指針->成員名

              Print3(struct Book* pb){
              	printf("書(shū)名為:%s\n", pb->name);
              	printf("價(jià)格為:%f\n", pb->price);
              	printf("書(shū)號(hào)為:%s\n", pb->id);
              }

              表達(dá)式求值

              一個(gè)表達(dá)式在求值時(shí),一部分取決于它的操作符的優(yōu)先級(jí)和結(jié)合性,一部分取決于編譯器自己的規(guī)則。我們寫出的表達(dá)式一定要讓編譯器的邏輯與自己的代碼邏輯相一致,否則就是沒(méi)用的代碼。與此同時(shí),有一些表達(dá)式中的操作數(shù)可能需要類型提升。

              隱式類型轉(zhuǎn)換

              在運(yùn)算的過(guò)程中,一些小字節(jié)的類型會(huì)向大字節(jié)的類型轉(zhuǎn)換后再加以運(yùn)算,整個(gè)過(guò)程是編譯器自動(dòng)一次完成的。

              整型提升

              如,short和char會(huì)轉(zhuǎn)化為int,再進(jìn)行運(yùn)算。不是說(shuō)只有不同類型數(shù)據(jù)運(yùn)算時(shí)才會(huì)發(fā)生類型轉(zhuǎn)換,而是為適應(yīng)CPU4個(gè)字節(jié)的運(yùn)算器,都會(huì)轉(zhuǎn)化為普通整型,這個(gè)過(guò)程被稱為整型提升。只要有運(yùn)算就會(huì)有整型提升。如:

              char a=1,b=2,c=3;
              ...
              char d=a+b+c;

              如這樣的一個(gè)例子,先將字符型的a,b,c整型提升為普通整型,然后進(jìn)行運(yùn)算,再放到d中,最后再發(fā)生截?cái)?,只取最后一個(gè)字節(jié),轉(zhuǎn)化回為字符型。

              如何整型提升

              按類型的符號(hào)位進(jìn)行整型提升。如:

              char c = -1;
              //11111111 11111111 11111111 11111111
              //11111111
              printf("%d\n",c);
              //11111111 11111111 11111111 11111111

              有符號(hào)數(shù)

              寫出變量的二進(jìn)制補(bǔ)碼按最高位符號(hào)位進(jìn)行填充得到的補(bǔ)碼再轉(zhuǎn)換成原碼

              無(wú)符號(hào)數(shù)

              最高位填充0

              如何得到c的補(bǔ)碼?(1)先把c當(dāng)成int類型然后,寫出32位補(bǔ)碼,(2)然后進(jìn)行截?cái)啵坏米詈?位。(3)最后再按此時(shí)的最高位填充,是0就填充0,反之則1。

              例題

              Example 1

              char a = 3;
              //00000000 00000000 00000000 00000011 - int a
              //00000011 - char a
              char b = 127;
              //00000000 00000000 00000000 01111111 - int b
              //01111111 - char b
              char c = a + b;
              //00000000 00000000 00000000 00000011 - int a 發(fā)生整型提升
              //00000000 00000000 00000000 01111111 - int b
              //00000000 00000000 00000000 10000010 - int c
              //10000010 - char c 發(fā)生截?cái)?
              printf("%d\n", c);
              //11111111 11111111 11111111 10000010 - int c - 補(bǔ)碼 發(fā)生整型提升
              //10000000 00000000 00000000 01111110 - int c - 原碼
              寫出a 和b的32位補(bǔ)碼進(jìn)行截?cái)?,存入?nèi)存整型提升,按最高位進(jìn)行填充進(jìn)行運(yùn)算進(jìn)行截?cái)?,再整型提升將所得補(bǔ)碼轉(zhuǎn)換回原碼

              如:

              C語(yǔ)言中操作符的介紹及用法

              我們?cè)诘玫絻蓚€(gè)變量的二進(jìn)制碼后,對(duì)其進(jìn)行整型提升,再對(duì)所得結(jié)果進(jìn)行截?cái)啵驗(yàn)橐嫒胱址妥兞縞中。又因?yàn)橐?d的形式打印變量c,再次對(duì)已經(jīng)截?cái)噙^(guò)的補(bǔ)碼(存入內(nèi)存中的都是補(bǔ)碼),進(jìn)行整型提升,轉(zhuǎn)換成原碼。

              Example 2

              char a = 0xb6;
              //10110110
              short b = 0xb600;
              //10110110 00000000
              int c = 0xb6000000;
              //10110110 00000000 00000000 00000000
              if (a == 0xb6)
              	//11111111 11111111 11111111 10110110 
              	//10000000 00000000 00000000 01001001
              	//10000000 00000000 00000000 01001010 - int a
              	//00000000 00000000 00000000 10110110 - 0xb6
              	printf("a");
              if (b == 0xb600)
              	//11111111 11111111 10110110 00000000
              	//10000000 00000000 01001001 11111111
              	//10000000 00000000 01001010 00000000 - int b
              	//00000000 00000000 10110110 00000000 - 0xb600
              	printf("b");
              if (c == 0xb60000)
              	//10110110 00000000 00000000 00000000 - int c
              	//10110110 00000000 00000000 00000000 - 0xb6000000
              	printf("c");
              首先我們寫出a,b,c 的二進(jìn)制補(bǔ)碼(都是正數(shù))。然后發(fā)現(xiàn)有運(yùn)算(==也是運(yùn)算),只要有運(yùn)算就要整型提升,整型提升后好巧不巧最高位都是1,默認(rèn)為負(fù)數(shù)了。這樣經(jīng)過(guò)原反補(bǔ)轉(zhuǎn)化后無(wú)論怎樣都是負(fù)數(shù),不會(huì)和0xb6和0xb600相等的。只有c本身就是默認(rèn)整型,不用提升。

              Example 3

              char c = 1;
              printf("%u\n", sizeof(c));//1
              printf("%u\n", sizeof(+c));//4
              printf("%u\n", sizeof(-c));//4

              計(jì)算sizeof(c)時(shí),沒(méi)有運(yùn)算所以沒(méi)有發(fā)生整型提升。取正取負(fù)也是運(yùn)算符,sizeof(±c)時(shí)(+c)和(-c)兩個(gè)表達(dá)式發(fā)生了整型提升,故變成了四個(gè)字節(jié)。

              算術(shù)轉(zhuǎn)換

              對(duì)于short和char需要整型提升為int,那浮點(diǎn)型,長(zhǎng)整型呢?對(duì)于這些類型,就不叫整型提升了,叫算術(shù)轉(zhuǎn)換。

              C語(yǔ)言中操作符的介紹及用法

              順序由高到低,當(dāng)精度低的類型與精度高的類型相運(yùn)算時(shí),會(huì)將低精度轉(zhuǎn)換為高精度,然后在和高精度數(shù)據(jù)進(jìn)行運(yùn)算。例:

              int a = 4;
              float f = 4.5f;
              f = a + f;
              printf("%f\n", f);//8.500000

              計(jì)算f時(shí)需要先把a(bǔ)轉(zhuǎn)化為單精度浮點(diǎn)型。

              操作符的屬性

              表達(dá)式的求值有三個(gè)影響因素:

              • 操作符的優(yōu)先級(jí)

              • 操作符的結(jié)合性

              • 是否控制求值順序

              兩個(gè)相鄰的操作符先執(zhí)行那個(gè)?

              先看優(yōu)先級(jí),優(yōu)先級(jí)相同看結(jié)合性。

              //表達(dá)式1.
              a*b+c*d+e*f;
              //表達(dá)式2
              c + --c;
              //表達(dá)式3
              int a = 1;
              a=(++i)+(++i)+(++i);

              C語(yǔ)言中操作符的介紹及用法

              這樣的表達(dá)式在不同的編譯器下,會(huì)跑出不同的結(jié)果,因?yàn)楦鱾€(gè)編譯器的標(biāo)準(zhǔn)不一樣。

              對(duì)于這樣的表達(dá)式,我們知道操作符的優(yōu)先級(jí)和結(jié)合性,但我們依然無(wú)法確定表達(dá)式計(jì)算的唯一路徑,所以這樣的代碼是不好的,寧愿多寫幾步,規(guī)范確定出表達(dá)式的唯一執(zhí)行路徑,也不要追求過(guò)分的簡(jiǎn)潔,這不是代碼的目的。

              總結(jié)

              我們寫出的表達(dá)式如果不能通過(guò)操作符的屬性確定唯一的計(jì)算路徑,那這個(gè)表達(dá)式就是存在問(wèn)題的。

              感謝各位的閱讀,以上就是“C語(yǔ)言中操作符的介紹及用法”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)C語(yǔ)言中操作符的介紹及用法這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

              向AI問(wèn)一下細(xì)節(jié)

              免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

              AI