警惕邏輯表示式中的無符號型別運算(C語言型別轉換)

2021-06-23 09:45:35 字數 3110 閱讀 6145

今天在處理邏輯表示式時遇到了類似以下程式的問題。if( strlen(tmp)-10 <0)這個條件怎麼都進不去。經過vs除錯可發現printf("%d",b-10<0);列印的結果為0。

#include

#include

int main()

{char tmp="12345";

unsigned int b;

b=5;

printf("%d",b-10<0);

return 1;

後來終於意識到應該是c語言型別自動轉換的緣故。因為strlen函式返回的型別為size_t,即乙個unsigned int。unsigned  int型別的值和int型的10相減的結果會自動轉換成unsigned型別。無符號型別的數值當然不會比0小了。

解決辦法:要麼把strlen的結果強制轉換成int,要麼語句換成if(strlen(tmp)<10)。

下面再溫習下c語言中的型別轉換知識,溫故而知新。

自動轉換遵循以下規則:

1)        若參與運算量的型別不同,則先轉換成同一型別,然後進行運算。

2)        轉換按資料長度增加的方向進行,以保證精度不降低。如int型和long型運算時,先把int量轉成long型後再進行運算。

a.若兩種型別的位元組數不同,轉換成位元組數高的型別

b.若兩種型別的位元組數相同,且一種有符號,一種無符號,則轉換成無符號型別

3)        所有的浮點運算都是以雙精度進行的,即使僅含float單精度量運算的表示式,也要先轉換成double型,再作運算。

4)        char型和short型參與運算時,必須先轉換成int型。

5)        在賦值運算中,賦值號兩邊量的資料型別不同時,賦值號右邊量的型別將轉換為左邊量的型別。如果右邊量的資料型別長度左邊長時,將丟失一部分資料,這樣會降低精度,丟失的部分按四捨五入向前捨入。

隱式轉換 

隱式型別轉換分三種,即算術轉換、賦值轉換和輸出轉換。

1.算術轉換

進行算術運算(加、減、乘、除、取餘以及符號運算)時,不同型別數招必須轉換成同一型別的資料才能運算,算術轉換原則為:

在進行運算時,以表示式中最長型別為主,將其他型別位據均轉換成該型別,如:

(1)若運算數中有double型或float型,則其他型別資料均轉換成double型別進行運算。

(2)若運算數中最長的型別為long型.則其他型別數均轉換成long型數。

(3)若運算數中最長型別為int型,則char型也轉換成int型進行運算。算術轉換是在運算過程中自動完成的。

2.賦值轉換

進行賦值操作時,賦值運算子右邊的資料型別必須轉換成賦值號左邊的型別,若右邊的資料型別的長度大於左邊,則要進行截斷或捨入操作。

下面用一例項說明:

char ch;

int i,result;

float f;

double d;

result=ch/i+(f*d-i);

(1)首先計算 ch/i,ch → int型,ch/i → int型。

(2)接著計算 f*d-i,由於最長型為double型,故f→double型,i→double型,f*d-i→double型。

(3)(ch/i) 和(f*d-i)進行加運算,由於f*d-i為double型,故ch/i→double型,ch/i+(f*d-i)→double型。

(4)由於result為int型,故ch/i+(f*d-i)→double→int,即進行截斷與捨入,最後取值為整型。

3.輸出轉換

在程式中將資料用printf函式以指定格式輸出時,當要輸出的鹽據型別與輸出格式不符時,便自動進行型別轉換,如乙個long型資料用整型格式(%d)輸出時,則相當於將long型轉換成整型(int)資料輸出;乙個字元(char)型資料用整型格式輸出時,相當於將char型轉換成int型輸出。

注意:較長型資料轉換成短型資料輸出時,其值不能超出短型資料允許的值範圍,否則轉換時將出錯。如:

long a=80000;

printf("%d",a);

執行結果為14464,因為int型允許的最大值為32767,80000超出此值,故結果取以32768為模的餘數,即進行如下取餘運算:

(80000-32768)-32768=14464;

輸出的資料型別與輸出格式不符時常常發生錯誤,如:

int d=9;

printf("%f",d);

或float c=3.2;

printf("%d",c);

將產生錯誤的結果。

同一句語句或表示式如果使用了多種型別的變數和常量(型別混用),c 會自動把它們轉換成同一種型別。以下是自動型別轉換的基本規則:

1. 在表示式中,char 和 short 型別的值,無論有符號還是無符號,都會自動轉換成 int 或者 unsigned int(如果 short 的大小和 int 一樣,unsigned short 的表示範圍就大於 int,在這種情況下,unsigned short 被轉換成 unsigned int)。因為它們被轉換成表示範圍更大的型別,故而把這種轉換稱為「公升級(promotion)」。

2. 按照從高到低的順序給各種資料型別分等級,依次為:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int 和 int。這裡有乙個小小的例外,如果 long 和 int 大小相同,則 unsigned int 的等級應位於 long 之上。char 和 short 並沒有出現於這個等級列表,是因為它們應該已經被公升級成了 int 或者 unsigned int。

3. 在任何涉及兩種資料型別的操作中,它們之間等級較低的型別會被轉換成等級較高的型別。

4. 在賦值語句中,= 右邊的值在賦予 = 左邊的變數之前,首先要將右邊的值的資料型別轉換成左邊變數的型別。也就是說,左邊變數是什麼資料型別,右邊的值就要轉換成什麼資料型別的值。這個過程可能導致右邊的值的型別公升級,也可能導致其型別降級(demotion)。所謂「降級」,是指等級較高的型別被轉換成等級較低的型別。

5. 作為引數傳遞給函式時,char 和 short 會被轉換成 int,float 會被轉換成 double。使用函式原型可以避免這種自動公升級。

當表示式中存在有符號型別和無符號型別時

以上這種表述是不準確的,正確的結論應為 當表示式中存在有符號型別和無符號型別時,預設情況下計算的結果將轉化為無符號型別 而對於計算過程而言,變數本身轉化為有符號還是無符號數,都不會改變在計算機中儲存的位狀態。參考如下 而如果將printf 函式中的列印型別換成u 即無符號10進製型別時 1 inti...

C 資料型別和表示式 1 無符號和有符號整型

對於熟悉的關鍵字,看到了,第一反應必須快速的給出正解,倘若不能,就說明還不夠熟悉。我問自己 資料型別有哪些?似乎一下子說不那麼全。習慣性的要列個圖,不求多高的要求,起碼要和課本上概括的差不多吧。說到資料型別,得記得住這些型別是佔多少位元組吧,畢竟我們是搞地基的。又可以重溫一遍資料型別了,再閉上眼睛回...

正規表示式的符號

表示法 描述正規表示式示例 literal 匹配文字字串的字面值literal aaare1 re2 匹配正規表示式re1或re2 aaa bbb 匹配任何字元 除了 n b.b 匹配字串起始部分 bin 匹配字串結束部分 sh 匹配0次或者多次前面出現的正規表示式 0 9 匹配1次或者多次前面出現...