欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

程序員都不知道C語言中的這些小細節(jié)

 更新時間:2021年05月29日 15:46:51   作者:捕獲一只小肚皮  
本文通過7到實例題目給大家展示C語言中的一些小細節(jié),很少有朋友真正的掌握,感興趣的朋友跟隨小編一起看看吧

既然題目都說了是小細節(jié),一來就介紹細節(jié)多沒意思啊,先坑坑大家再詳細介紹吧,嘿嘿.直接上7個題吧,看看你能做對幾個呢?


計算型細節(jié)

①:

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

您想想這個題的答案是多少?先不要看后面的答案哦
答案是 -126, 嘿嘿,是不是答錯了呢?先不要著急,繼續(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;
}

您想想這個題的答案是什么呢? 先不要看后面的答案哦
答案是 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,嘿嘿,是不是又回答錯誤,先不要著急,再看看后面的題

表達式細節(jié)

①:

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

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

③:

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

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

④:

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

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

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

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

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


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

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

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

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

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

  • 算術(shù)提升:在最前面補符號位數(shù)字,直到32位
  • 邏輯提升:無論什么都只補0,直到32位

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

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

下面有張字符類型原碼補碼反碼的對應(yīng)理解圖
在這里插入圖片描述


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

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



在這里插入圖片描述



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

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

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

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

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

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

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

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

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

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

算術(shù)提升方向:
在這里插入圖片描述


1.3 操作符屬性

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

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


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

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

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

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

1.3.3 什么是求值順序?

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

下面有兩個關(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還是增加了的,因為后置加加是 先使用再加加

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


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

在這里插入圖片描述
其中優(yōu)先級從上往下逐漸降低

1.3.4 第四題講解

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

ret = c + --c中有兩個操作符號,先看優(yōu)先級,--的優(yōu)先級高于+,所以決定了先算–c,但是+號左邊的c是什么時候準(zhǔn)備的呢? 我們知道,c語言是編譯性語言,在代碼寫好以后是需要先進行編譯為機器語言,然后執(zhí)行的.那么在編譯時候,+號左邊的值是在--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;
}

這個是同樣的道理,雖然知道優(yōu)先級,但是結(jié)合性中的操作數(shù)什么時候準(zhǔn)備不確定,你看看在不同的編譯器操作的結(jié)果:
在這里插入圖片描述
同樣是個垃圾代碼

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)用符號優(yōu)先級最高,但是這里有三個,到底先調(diào)用哪個呢??這又不確定了.

  • vs編譯器是從左往右依次調(diào)用的,結(jié)果為-10.
  • 但是其他編譯器呢??大家去試試gcc,codeblocks,Devc++,你一定會發(fā)現(xiàn)完全不一樣.

1.3.7 第七題講解

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

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

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

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

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

總結(jié): 知道了什么是整型提升與截斷知道了什么是算術(shù)轉(zhuǎn)換知道了什么操作符的屬性,以后不能寫出這種類似的垃圾代碼.

以上就是程序員都不知道C語言中的這個小細節(jié)的詳細內(nèi)容,更多關(guān)于C語言小細節(jié)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論