c語言,資料型別轉換!又要掉頭髮了!

2021-09-27 13:05:42 字數 3452 閱讀 8817

在執行算術運算時,計算機比c語言的限制更多。為了讓計算機執行算術運算,通常要求運算元有相同的大小(即位的數量相同),並且要求儲存的方式也相同。計算機可能可以直接將兩個16位整數相加,但是不能直接將16位整數和32位整數相加,也不能直接將32位整數和32位浮點數相加。另一方面,c語言允許在表示式中混合使用基本資料型別。在單獨乙個表示式中可以組合整數、浮點數,甚至是字元。當然,在這種情況下c語言編譯器可能需要生成一些指令將某些運算元轉換成不同型別,使得硬體可以對表示式進行計算。例如,如果對16位int型數和32位long int型數進行加法操作,那麼編譯器將安排把16位int型值轉換成32位值。如果是int型資料和float型資料進行加法操作,那麼編譯器將安排把int型值轉換成為float格式。這個轉換過程稍微複雜一些,因為int型值和float型值的儲存方式不同。因為編譯器可以自動處理這些轉換而無需程式設計師介入,所以這類轉換稱為隱式轉換(implicit conversion)。c語言還允許程式設計師通過使用強制運算子執行顯式轉換(explicit conversion)。首先討論隱式轉換,,執行隱式轉換的規則有些複雜,主要是因為c語言有大量不同的基本資料型別(6種整型和3種浮點型,這還不包括字元型)。

當發生下列情況時會進行隱式轉換:

.當算術表示式或邏輯表示式中運算元的型別不相同時。(c語言執行所謂的常用算術轉換。)

.當賦值運算子右側表示式的型別和左側變數的型別不匹配時。

.當函式呼叫中使用的引數型別與其對應的引數的型別不匹配時。

.當return語句中表示式的型別和函式返回值的型別不匹配時。

隱式型別轉換規則:

c語言自動轉換不同型別的行為稱之為隱式型別轉換 ,轉換的基本原則是:低精度型別向高精度型別轉換,具體是:

int -> unsigned int -> long -> unsigned long -> long long -> unsigned long long -> float -> double -> long double

注意,上面的順序並不一定適用於你的機器,比如當int和long具有相同字長時,unsigned int的精度就會比long的精度高(事實上大多數針對32機的編譯器都是如此)。另外需要注意的一點是並沒有將char和short型寫入上式,原因是他們可以被提公升到int也可能被提公升到unsigned int。

提公升資料的精度通常是乙個平滑無損害的過程,但是降低資料的精度可能導致真正的問題。原因很簡單:乙個較低精度的型別可能不夠大,不能存放乙個具有更高精度的完整的資料。乙個1位元組的char變數可以存放整數101但不能存放整數12345。當把浮點型別資料轉換為整數型別時,他們被趨零截尾或捨入。

當把有符號運算元和無符號運算元整合時,會通過把符號位看成數的位的方法把有符號運算元"轉換"成無符號的值.這條規則可能會導致某些隱蔽的程式設計錯誤。

假設int型的變數i的值為-10,而且unsigned int型的變數u的值為10。如果用<運算子比較變數i和變u,那麼期望的結果應該是1(真)。但是,在比較前,變數i轉換成為unsigned int型別。因為負數不能被表示成無符號整數,所以轉換後的數值將不再為-10,而是乙個大的正數(將變數i中的位看作是無符號數).因此i

由於此類陷阱的存在,所以最好盡最避免使用無符號整數,特別是不要把它和有符號整數混合使用。

先來看一段簡單的**:

執行結果:

randy@ubuntu:~/c_language$ ./a.out 

now i = 7.

是不是很奇怪?為什麼沒有打出line13的x = ?。

是這樣的。這個小例子有三點值得注意:

1.sizeof()是運算子,返回型別是無符號的,即非負數。

2.if語句在singned int和unsigned int之間進行判斷語句,根據c語言的整型提公升規則,int -> unsigned int

3.i = -1被公升級為無符號型,值究竟是多少?這要用到整型轉換規則:k&r上這樣解釋,將任何整數轉換為某種指定的無符號數型別數的方法是:以該無符號數型別能夠表示的最大值加1為摸,找出與此整數同餘的最小的非負值。聽著很拗口,其實說白了,只要知道原整數的二進位制表達方法,再用要即將轉換的型別去解析,就得到公升級後的值了。 比如-1,負數在計算機裡用補碼表示為0xffffffff,那公升級成無符號型之後,值就是0xffffffff,顯然比total_elements(7)大。

強制型別轉換:

通常我們應該避免自動型別轉換,當我們需要手動指定乙個準確的資料型別時,我們可以用強制型別轉換機制來達到我們的目的,使用方法很簡單,在需要強制轉換型別的變數或常量前面加上(type),例如(double)i; 即把變數 i 強制轉換成double型。

思考下面這個例子:

long int i;

int j = 10000;

i = j*j; /*wrong*/

乍看之下,這條語句沒有問題。表示式j*j的值是1000000,並且變數i是long int型的,所

以i應該能很容易地儲存這種大小的值,不是嗎?問題是,當兩個int型值相乘時,結果也應該

是int型別的,但是j*j的結果太大,以致於在某些機器上無法表示成int型別.在這樣的機器

上,會給變數i賦乙個無意義的值。幸運的是,可以使用強制型別轉換避免這種問題的發生:

i=(long int)j*j

因為強制運算子的優先順序高於*,所以第乙個變數j會被轉換成long int型別,同時也迫使第

二個j進行轉換。

注意語句

i==(long int)(j*j)/**wrong***/

是不對的,因為溢位在強制型別轉換之前就己經發生了。

q&a:

問:如果"溢位"會發生什麼?比如,兩個數相加的結果過大而無法儲存.

答:這取決於數是有符號型的還是無符號型的。當溢位發生在有符號數的操作上時,依據c語言的標準,

結果是"未定義的"。我們無法準確說出結果是什麼,因為這依賴於機器的行為。程式甚至可能會

異常中斷(對除以零的典型反應)。

但是,當溢位發生在無符號數的操作上時,結果是定義了的:可以獲得正確答案對2n進行取模運算

的結果,這裡的n是用於儲存結果使用的位數。例如,如果用1加上無符號的16位數65535,那麼結

果肯定是65536 (已經溢位,但計算機能正確表示其值).

學習推薦路線:

C語言資料型別轉換

自動轉換發生在不同資料型別的量混合運算時,由編譯系統自動完成。自動轉換遵循以下規則 若參與運算量的型別不同,則先轉換成同一型別,然後進行運算。轉換按資料長度增加的方向進行,以保證精度不降低。如int型和long型運算時,先把int量轉成long型後再進行運算。所有的浮點運算都是以雙精度進行的,即使僅...

C語言資料型別轉換

變數的資料型別是可以轉換的。轉換的方法有兩種,一種是自動轉換,一種是強制轉換。自動轉換發生在不同資料型別的量混合運算時,由編譯系統自動完成。自動轉換遵循以下規則 若參與運算量的型別不同,則先轉換成同一型別,然後進行運算。轉換按資料長度增加的方向進行,以保證精度不降低。如int型和long型運算時,先...

C語言資料型別轉換

資料型別轉換就是將資料 變數 表示式的結果 從一種型別轉換到另一種型別。例如,為了儲存小數你可以將int型別的變數轉換為double型別。資料型別轉換的一般格式為 type name expressiontype name為要轉換到的資料型別,expression為表示式。例如 float a 把a...