溫馨提示×

溫馨提示×

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

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

C語言中的細(xì)節(jié)分析

發(fā)布時(shí)間:2021-05-31 09:48:16 來源:億速云 閱讀:141 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹了C語言中的細(xì)節(jié)分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

計(jì)算型細(xì)節(jié)

①:

#include <stdio.h>
int main()
{
	char a = 3;
	char b = 127;
	char c = a + b;
	printf("結(jié)果是:%d",c);
	return 0;
}

您想想這個(gè)題的答案是多少?先不要看后面的答案哦
答案是 -126, 嘿嘿,是不是答錯(cuò)了呢?先不要著急,繼續(xù)看下面的題

②:

#include <stdio.h>
int main()
{
	char a = 0xb6;
	short b = 0xb600;
	int c = 0xb6000000;
	if(a==0xb6)
		printf("a");
	if(b==0xb600)
		printf("b");
	if(c==0xb6000000)
		printf("c");
	return 0;
}

您想想這個(gè)題的答案是什么呢? 先不要看后面的答案哦
答案是 c,嘿嘿,是不是又回答錯(cuò)誤,先不要著急,再看看后面的題

③:

#include <stdio.h>
int main()
{
	 char c = 1;
	 printf("%u\n", sizeof(c));
	 printf("%u\n", sizeof(+c));
	 printf("%u\n", sizeof(-c));
	 return 0;
}

您想想這個(gè)題的答案是什么呢? 先不要看后面的答案哦
答案是1 4 4,嘿嘿,是不是又回答錯(cuò)誤,先不要著急,再看看后面的題

表達(dá)式細(xì)節(jié)

①:

#include <stdio.h>
int main()
{
	 int c = 3;
	 int ret = c + --c;
	 printf("%d",ret);  
	 return 0;
}

您想想這個(gè)題的答案是什么呢? 先不要看后面的答案哦
答案是 5 或者 4,是不確定的,嘿嘿,是不是又回答錯(cuò)誤,先不要著急,再看看后
面的題

②:

int main()
{
	 int i = 10;
	 i = i-- - --i * ( i = -3 ) * i++ + ++i;
	 printf("i = %d\n", i);
	 return 0;
}

您想想這個(gè)題的答案是什么呢? 先不要看后面的答案哦
答案有很多個(gè),在不同的編譯器結(jié)果不同,也就是說還是不能確定結(jié)果,嘿嘿,是不是仍然回答錯(cuò)誤了,先不要著急,再看看后面的題

③:

#include <stdio.h>
int fun()
{
     static int count = 1;
     return ++count;
}

int main()
{
     int answer;
     answer = fun() - fun() * fun();
     printf( "%d\n", answer);//輸出多少?
     return 0;
}

您想想這個(gè)題的答案是什么呢? 先不要看后面的答案哦
答案是 不同編譯器不同結(jié)果 ,嘿嘿,是不是又回答錯(cuò)誤,先不要著急,再看看后面的題

④:

#include <stdio.h>
int main()
{
	 int i = 1;
	 int ret = (++i) + (++i) + (++i);
	 printf("%d\n", ret);
	 printf("%d\n", i);
	 return 0;
}

這是最后一個(gè)題了,你目前答對(duì)了幾道了呢??請(qǐng)?jiān)谠u(píng)論回答試試.嘿嘿
這個(gè)題的答案是 不同編譯器不同結(jié)果

大家回答對(duì)了幾道題?歡迎評(píng)論

 1.現(xiàn)在正式講解上面所有的題設(shè)計(jì)到的內(nèi)容--------表達(dá)式求值

表達(dá)式求值的順序一部分是由操作符的優(yōu)先級(jí)和結(jié)合性決定。
同樣,有些表達(dá)式的操作數(shù)在求值的過程中可能需要轉(zhuǎn)換為其他類型。


1.1隱式類型轉(zhuǎn)換 (整型截?cái)嗯c提升)

什么是隱式類型轉(zhuǎn)換,整型提升,整型截?cái)?

C的整型算術(shù)運(yùn)算總是至少以滿足整型類型的精度來進(jìn)行的。
為了獲得這個(gè)精度,表達(dá)式中若有charshort類型必須在使用之前轉(zhuǎn)換稱為整型,這個(gè)過程叫做 整型提升
.
一個(gè)較大數(shù)據(jù)類型存儲(chǔ)在較小數(shù)據(jù)類型中的過程叫做整型截?cái)?/code>,比如整型a = 500,但是a把他的值放到了字符型b中,b不能完全存放a,就會(huì)發(fā)生整型截?cái)?/code>
.
而這個(gè)轉(zhuǎn)換行為叫做 隱式類型轉(zhuǎn)換

1.1.1 第一題講解

#include <stdio.h>
int main()
{
	char a = 3;
	char b = 127;
	char c = a + b;
	printf("結(jié)果是:%d",c);
	return 0;
}

我們知道計(jì)算機(jī)中一切都是操作的補(bǔ)碼.所以這里也是一樣,(不明白原碼補(bǔ)碼反碼的自己去百度下哦).
其中 正數(shù)的 原碼 反碼 補(bǔ)碼 一模一樣
… …負(fù)數(shù)的 補(bǔ)碼是反碼加一,反碼是原碼除了符號(hào)位所有位都按位取反

a只有1個(gè)字節(jié),他的補(bǔ)碼是00000011(二進(jìn)制)
b只有1個(gè)字節(jié),他的補(bǔ)碼是01111111(二進(jìn)制)
a加b,進(jìn)行了算術(shù)操作,需要提升到4個(gè)字節(jié).而整型提升有兩種方式

  • 算術(shù)提升:在最前面補(bǔ)符號(hào)位數(shù)字,直到32位

  • 邏輯提升:無論什么都只補(bǔ)0,直到32位

大多數(shù)計(jì)算器都是進(jìn)行的算術(shù)提升,這里便講解算術(shù)提升.

a算術(shù)提升后就是00000000000000000000000000000011
b算術(shù)提升后就是00000000000000000000000001111111
a+b的結(jié)果是------00000000000000000000000010000010
存進(jìn)c里面,c又只有1個(gè)字節(jié),所以發(fā)生整型截?cái)?只存取最后8位
10000010
此時(shí)c存取的是補(bǔ)碼,且c是有符號(hào)型,記住了!!,打印顯示時(shí)候會(huì)還原位原碼的,該補(bǔ)碼對(duì)應(yīng)的數(shù)字就是 -126

下面有張字符類型原碼補(bǔ)碼反碼的對(duì)應(yīng)理解圖
C語言中的細(xì)節(jié)分析


所以有符號(hào)的范圍是 [-128,127]
無符號(hào)的范圍是[0,255]

變成圓圈更好理解,自己按照有無符號(hào)對(duì)應(yīng)去找就行.



C語言中的細(xì)節(jié)分析



1.1.2 第二題講解

#include <stdio.h>
int main()
{
	char a = 0xb6;
	short b = 0xb600;
	int c = 0xb6000000;
	if(a==0xb6)
		printf("a");
	if(b==0xb600)
		printf("b");
	if(c==0xb6000000)
		printf("c");
	return 0;
}

0xb6的二進(jìn)制是 00000000000000000000000010110110
存進(jìn)去a中,發(fā)生截?cái)?得到1011 0110
0xb600的二進(jìn)制是00000000 00000000 10110110 00000000
存進(jìn)去b中發(fā)生截?cái)?得到10110110 00000000
0xb600000010110110 00000000 00000000 00000000
存進(jìn)去c中剛剛好.

a此時(shí)存的是補(bǔ)碼,a又與0xb6比較,參與了運(yùn)算,所以又整型提升為
11111111 11111111 11111111 10110110,

整型提升后的數(shù)字與0xb6的二進(jìn)制不一樣,所以不等.

b此時(shí)存的是補(bǔ)碼,b又與0xb600比較,參與了運(yùn)算,所以又整型提升為
11111111 11111111 10110110 00000000

整型提升后的數(shù)字與0xb600的二進(jìn)制不一樣,所以不等

c此時(shí)存的是10110110 00000000 00000000 00000000,注意哦~,有人可能會(huì)問0xb6000000是正數(shù)啊,不!!!!!,字面常量只要不帶符號(hào)就是默認(rèn)int類型.所以此時(shí)0xb6000000的整數(shù)值是超過int的,就會(huì)認(rèn)為它此時(shí)的二進(jìn)制是負(fù)數(shù)的補(bǔ)碼.所以c與0xb6000000是相等的.



1.1.3 第三題講解

#include <stdio.h>
int main()
{
	 char c = 1;
	 printf("%u\n", sizeof(c));
	 printf("%u\n", sizeof(+c));
	 printf("%u\n", sizeof(-c));
	 return 0;
}

sizeof 測量的是類型屬性的值.
c的類型是 char,只有一個(gè)字節(jié),所以答案是1
+c,+是單目操作符,與c在一起發(fā)生了整型提升,變成了int,所以是4個(gè)字節(jié),答案是 4
-c,同樣的道理,仍然是4

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

上面我們說到,如果操作數(shù)大小 小于int,會(huì)發(fā)生整型提升,但是如果都是大于等于int大小的類型參與算術(shù)運(yùn)算呢?? 這里就會(huì)涉及到 算術(shù)轉(zhuǎn)換.
什么是算術(shù)轉(zhuǎn)換呢? 比如下面的例子:

#include <stdio.h>
int main()
{
	int a = -127;
	unsigned int b =  129;
	if(a > b)
	{
		printf("a會(huì)大于b");
	}
	return 0;
}

結(jié)果會(huì)打印 a會(huì)大于b
因?yàn)檫@就是算術(shù)轉(zhuǎn)換,即還是需要滿足同類型運(yùn)算,unsigned int 比int 高,所以a的值會(huì)默認(rèn)是 無符號(hào)的,a就會(huì)比b大.

算術(shù)提升方向:
C語言中的細(xì)節(jié)分析


1.3 操作符屬性

復(fù)雜表達(dá)式的求值有三個(gè)影響的因素。

操作符的優(yōu)先級(jí)操作符的結(jié)合性是否控制求值順序。


1.3.1 什么是優(yōu)先級(jí)?

就是決定先計(jì)算什么.比如d = a + b*c. 因?yàn)?code>*的優(yōu)先級(jí)高于+,所以,先算b*c,再算+

1.3.2 什么是結(jié)合性?

就是同樣優(yōu)先級(jí),就決定從哪個(gè)方向計(jì)算.比如d = a * b * c ,因?yàn)檫B續(xù)的*,優(yōu)先級(jí)已經(jīng)沒有用了,所以此時(shí)就是結(jié)合性,*的結(jié)合性是從左到右.也就是說先計(jì)算a*b 然后計(jì)算*c.

1.3.3 什么是求值順序?

就是只計(jì)算哪邊.c語言的操作符具有求值順序的只有寥寥幾個(gè),比如||, && , !
求值順序到底什么意思呢?
比如a等于0,b等于2,c等于3,d = a && b && c,d的值最后是0,但是在運(yùn)算時(shí)候只到a就完結(jié)了,因?yàn)?code>&&
是只要碰到假就是假,后面的真假已經(jīng)無關(guān),a為0,是假,所以后面不用再管.這就是求值順序.

下面有兩個(gè)關(guān)于求值順序的小練習(xí):

#include <stdio.h>
int main()
{
    int i = 0,a=0,b=2,c =3,d=4;
    i = a++ && ++b && d++;
    printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
    return 0;
}

答案是 1 2 3 4.理由: a是后置++,先使用a=0的值,一開始就遇到假了,后面不再執(zhí)行.但是a還是增加了的,因?yàn)楹笾眉蛹邮?先使用再加加

#include <stdio.h>
int main()
{
    int i = 0,a=0,b=2,c =3,d=4;
    i = ++a || ++b || d++;
    printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
    return 0;
}

答案:1 2 3 4,前置++,即先加加,a成了1,因?yàn)?code>||一遇到真就結(jié)束,不再管后面真假.所以只有a變化了.


這里有張操作符屬性的表:

C語言中的細(xì)節(jié)分析
其中優(yōu)先級(jí)從上往下逐漸降低

1.3.4 第四題講解

#include <stdio.h>
int main()
{
	 int c = 3;
	 int ret = c + --c;
	 printf("%d",ret);  
	 return 0;
}

ret = c + --c中有兩個(gè)操作符號(hào),先看優(yōu)先級(jí),--的優(yōu)先級(jí)高于+,所以決定了先算–c,但是+號(hào)左邊的c是什么時(shí)候準(zhǔn)備的呢? 我們知道,c語言是編譯性語言,在代碼寫好以后是需要先進(jìn)行編譯為機(jī)器語言,然后執(zhí)行的.那么在編譯時(shí)候,+號(hào)左邊的值是在--c之前就已經(jīng)編譯好了呢,還是--c之后編譯好了呢?這是不確定的.

  • 在vs編譯器下答案是 4,他是在--c之后準(zhǔn)備好了c

  • 在gcc編譯器下答案是 5,他是在--c之前準(zhǔn)備好了c

所以: 這是問題代碼,我們以后不要寫這樣的垃圾代碼.

1.3.5 第五題講解

int main()
{
	 int i = 10;
	 i = i-- - --i * ( i = -3 ) * i++ + ++i;
	 printf("i = %d\n", i);
	 return 0;
}

這個(gè)是同樣的道理,雖然知道優(yōu)先級(jí),但是結(jié)合性中的操作數(shù)什么時(shí)候準(zhǔn)備不確定,你看看在不同的編譯器操作的結(jié)果:
C語言中的細(xì)節(jié)分析
同樣是個(gè)垃圾代碼

1.3.6 第六題講解

#include <stdio.h>
int fun()
{
     static int count = 1;
     return ++count;
}

int main()
{
     int answer;
     answer = fun() - fun() * fun();
     printf( "%d\n", answer);//輸出多少?
     return 0;
}

()函數(shù)調(diào)用符號(hào)優(yōu)先級(jí)最高,但是這里有三個(gè),到底先調(diào)用哪個(gè)呢??這又不確定了.

  • vs編譯器是從左往右依次調(diào)用的,結(jié)果為-10.

  • 但是其他編譯器呢??大家去試試gcc,codeblocks,Devc++,你一定會(huì)發(fā)現(xiàn)完全不一樣.

1.3.7 第七題講解

再說這個(gè)題之前,博主一定要批判某些高校,為什么呢??學(xué)校教大家++符號(hào)時(shí)候是不是最喜歡用這種類型來考大家?在這明確告訴大家,這完全是在浪費(fèi)時(shí)間!!!因?yàn)檫@種代碼根本沒有意義!!!.就是垃圾代碼

#include <stdio.h>
int main()
{
	 int i = 1;
	 int ret = (++i) + (++i) + (++i);
	 printf("%d\n", ret);
	 printf("%d\n", i);
	 return 0;
}

首先,()括號(hào)的優(yōu)先級(jí)最高,但是有三個(gè),到底先計(jì)算哪個(gè)?
其次,一個(gè)i的變化,會(huì)不會(huì)影響另外的?這里也不確定.和第四題我們說的那個(gè)編譯之前c到底什么時(shí)候準(zhǔn)備一樣.不確定.!!!

vs編譯器的值是 12 4gcc編譯器的值是 10 4
不同的編譯器不同的值,結(jié)果不一樣,這樣的代碼不配叫代碼.!!!

所以,以后看到這種題直接跳過,沒有意義.

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“C語言中的細(xì)節(jié)分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!

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

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

AI