中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

C語言中的細節分析

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

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

計算型細節

①:

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

您想想這個題的答案是多少?先不要看后面的答案哦
答案是 -126, 嘿嘿,是不是答錯了呢?先不要著急,繼續看下面的題

②:

#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;
}

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

③:

#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;
}

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

表達式細節

①:

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

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

②:

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

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

③:

#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;
}

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

④:

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

這是最后一個題了,你目前答對了幾道了呢??請在評論回答試試.嘿嘿
這個題的答案是 不同編譯器不同結果

大家回答對了幾道題?歡迎評論

 1.現在正式講解上面所有的題設計到的內容--------表達式求值

表達式求值的順序一部分是由操作符的優先級和結合性決定。
同樣,有些表達式的操作數在求值的過程中可能需要轉換為其他類型。


1.1隱式類型轉換 (整型截斷與提升)

什么是隱式類型轉換,整型提升,整型截斷?

C的整型算術運算總是至少以滿足整型類型的精度來進行的。
為了獲得這個精度,表達式中若有charshort類型必須在使用之前轉換稱為整型,這個過程叫做 整型提升
.
一個較大數據類型存儲在較小數據類型中的過程叫做整型截斷,比如整型a = 500,但是a把他的值放到了字符型b中,b不能完全存放a,就會發生整型截斷
.
而這個轉換行為叫做 隱式類型轉換

1.1.1 第一題講解

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

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

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

  • 算術提升:在最前面補符號位數字,直到32位

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

大多數計算器都是進行的算術提升,這里便講解算術提升.

a算術提升后就是00000000000000000000000000000011
b算術提升后就是00000000000000000000000001111111
a+b的結果是------00000000000000000000000010000010
存進c里面,c又只有1個字節,所以發生整型截斷,只存取最后8位
10000010
此時c存取的是補碼,且c是有符號型,記住了!!,打印顯示時候會還原位原碼的,該補碼對應的數字就是 -126

下面有張字符類型原碼補碼反碼的對應理解圖
C語言中的細節分析


所以有符號的范圍是 [-128,127]
無符號的范圍是[0,255]

變成圓圈更好理解,自己按照有無符號對應去找就行.



C語言中的細節分析



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的二進制是 00000000000000000000000010110110
存進去a中,發生截斷,得到1011 0110
0xb600的二進制是00000000 00000000 10110110 00000000
存進去b中發生截斷,得到10110110 00000000
0xb600000010110110 00000000 00000000 00000000
存進去c中剛剛好.

a此時存的是補碼,a又與0xb6比較,參與了運算,所以又整型提升為
11111111 11111111 11111111 10110110,

整型提升后的數字與0xb6的二進制不一樣,所以不等.

b此時存的是補碼,b又與0xb600比較,參與了運算,所以又整型提升為
11111111 11111111 10110110 00000000

整型提升后的數字與0xb600的二進制不一樣,所以不等

c此時存的是10110110 00000000 00000000 00000000,注意哦~,有人可能會問0xb6000000是正數啊,不!!!!!,字面常量只要不帶符號就是默認int類型.所以此時0xb6000000的整數值是超過int的,就會認為它此時的二進制是負數的補碼.所以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,只有一個字節,所以答案是1
+c,+是單目操作符,與c在一起發生了整型提升,變成了int,所以是4個字節,答案是 4
-c,同樣的道理,仍然是4

1.2算術轉換

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

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

結果會打印 a會大于b
因為這就是算術轉換,即還是需要滿足同類型運算,unsigned int 比int 高,所以a的值會默認是 無符號的,a就會比b大.

算術提升方向:
C語言中的細節分析


1.3 操作符屬性

復雜表達式的求值有三個影響的因素。

操作符的優先級操作符的結合性是否控制求值順序。


1.3.1 什么是優先級?

就是決定先計算什么.比如d = a + b*c. 因為*的優先級高于+,所以,先算b*c,再算+

1.3.2 什么是結合性?

就是同樣優先級,就決定從哪個方向計算.比如d = a * b * c ,因為連續的*,優先級已經沒有用了,所以此時就是結合性,*的結合性是從左到右.也就是說先計算a*b 然后計算*c.

1.3.3 什么是求值順序?

就是只計算哪邊.c語言的操作符具有求值順序的只有寥寥幾個,比如||, && , !
求值順序到底什么意思呢?
比如a等于0,b等于2,c等于3,d = a && b && c,d的值最后是0,但是在運算時候只到a就完結了,因為&&是只要碰到假就是假,后面的真假已經無關,a為0,是假,所以后面不用再管.這就是求值順序.

下面有兩個關于求值順序的小練習:

#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的值,一開始就遇到假了,后面不再執行.但是a還是增加了的,因為后置加加是 先使用再加加

#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,因為||一遇到真就結束,不再管后面真假.所以只有a變化了.


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

C語言中的細節分析
其中優先級從上往下逐漸降低

1.3.4 第四題講解

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

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

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

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

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

1.3.5 第五題講解

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

這個是同樣的道理,雖然知道優先級,但是結合性中的操作數什么時候準備不確定,你看看在不同的編譯器操作的結果:
C語言中的細節分析
同樣是個垃圾代碼

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;
}

()函數調用符號優先級最高,但是這里有三個,到底先調用哪個呢??這又不確定了.

  • vs編譯器是從左往右依次調用的,結果為-10.

  • 但是其他編譯器呢??大家去試試gcc,codeblocks,Devc++,你一定會發現完全不一樣.

1.3.7 第七題講解

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

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

首先,()括號的優先級最高,但是有三個,到底先計算哪個?
其次,一個i的變化,會不會影響另外的?這里也不確定.和第四題我們說的那個編譯之前c到底什么時候準備一樣.不確定.!!!

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

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

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平安县| 乾安县| 安徽省| 漾濞| 张家口市| 西充县| 葵青区| 盈江县| 汾阳市| 阿克| 溧水县| 屯门区| 山东| 磐石市| 平阴县| 峡江县| 祁东县| 横峰县| 馆陶县| 黄山市| 文安县| 唐海县| 丰原市| 武威市| 金寨县| 板桥市| 贡山| 邛崃市| 庆元县| 龙岩市| 拉萨市| 铅山县| 营山县| 滦平县| 筠连县| 抚顺县| 专栏| 淮南市| 漯河市| 蒲江县| 社会|