1. 程式人生 > >C語言的型別系統-編碼, 型別轉換及其規範

C語言的型別系統-編碼, 型別轉換及其規範

C語言的型別系統

——————

組合語言將儲存器看成一個虛擬儲存器,即將儲存器看成一個大的位元組陣列,組合語言並沒有提供型別系統.  C語言將位元組陣列抽象成不同長度的位元組陣列.本文介紹C語言的型別系統以及型別之間相互轉換的原則.

C語言的資料型別

————

C語言的型別是相當豐富的,它提供多種型別. C語言的資料型別具體有:

1.基本型別:整型(short/int/long/longlong (C99)),浮點型(float/double/long double(C99)),字元型(char-可以歸整型),列舉型.

2.構造型別:陣列,結構,聯合.

3.指標型別.

4.空型別.

C標準明確規定

char型佔1個位元組,其他資料型別的大小是Implementation-defined.但是現代處理器和編譯器都採用ILP32LP64規範.見下表:

型別

ILP32規範(IA32)

ILP32對應的Intel資料型別

LP64(x86-64)

LP64對應的Intel資料型別

char

1

位元組

1

位元組

short

2

2

int

4

雙字

4

雙字

long

4

雙字

8

四字

long long

8

-----

8

四字

指標

4

雙字

8

四字

float

4

單精度

4

單精度

double

8

雙精度

8

雙精度

long double

10/12

擴充套件精度

10/16

擴充套件精度

本文是IA32,故採用ILP32規範進行分析.

計算機編碼

————

現代計算機資訊的表示,儲存,傳輸都是都是通過二級制來完成的(具體的原因元芳懂得).通過二進位制數字系統我們可以進行編碼,諸如對整數,負數,浮點數近似值,字元等進行編碼.

計算機的三種重要的數字表示:

1.無符號(unsigned)編碼.---->對應C語言的無符號整數.

假設一個整數資料型別有

w.設位向量x=[xw-1, xw-1,,x0].定義一個函式B2Uw(Binary toUnsigned).

    B2Uw(x) =(i=0w-1)xi2i

2.補碼(two's-complement)編碼.---->對應C語言的整數.

假設一個整數資料型別有w.設位向量x=[xw-1, xw-1,,x0].定義一個函式B2Tw(Binary toTwo's-complement).

    B2Tw(x) =-xw-12w-1+(i=0w-2)xi2i     (將最高有效位解釋為負權)

3.浮點數(floating-point)編碼.----->對應C語言的float/double/longdouble.

    C標準沒有規定浮點數必須使用IEEE 754標準,但是現代計算機普通使用IEEE754.詳見IEEE 754浮點數的表示(也可以參考csapp的第二章).

C語言的型別轉換

————

C語言的型別轉換分為隱式型別轉換和強制型別轉換

1.型別轉換的原理.

(1).同類型的有符號和無符號數之間的轉換(位模式的重新解釋).

典型案例: unsigned<->int

    

有符號和無符號之間轉換時候,位模式並沒有變化.

(2).符號位擴充套件(保證值不變->可以使用數學歸納法證明).

典型案例: short->int; unsigned short-> unsigned int

    

    C規範並沒有要求符號位擴充套件,但是符號位擴充套件能夠保證有符號的數值不變.所以大多數實現都是有符號擴充套件.

(3). 截斷原理.

典型案例: int->short; unsigned int->unsigned short

    

有符號和無符號的截斷都是高位截斷.

(4).轉換原理.

典型案例: int->float/double; float->double

瞭解了IEEE754浮點數標準,很容易理解int, float,double之間如何轉換. int->float/double首先就是要規格化,然後舍入.再轉換.

a. int->float(32->32).顯然,不會溢位,但是會舍入(精度損失).

    b. int/float->double.不會溢位,也不會舍入(不會有精度損失).

    c. double->float.值可能會溢位(+Infinity or -Infinity),可能會舍入.

    d. float/double->int.可能會溢位(C標準沒有規範會溢位成什麼結果. Intel相容機通常是[10000]),0舍入. (+1.9->1,-1.9->-1).

2. C標準的規範.

(1).隱式型別轉換(Implicit Conversion)[3]

(2).強制型別轉換(Explicit Conversion or Type Cast)

3.編譯器處理型別轉換

例如:

src_t v;

dest_t*p;

*p =(dest_t)v;

假定: v放在%eax, p放在%edx.

src_t

dest_t

指令

型別

int

int

movl %eax, (%edx)

-

char

int

movsbl %al, (%edx)

符號位擴充套件

char

unsigned

movsbl %al, (%edx)

char->int->unsigned

unsigned char

int

movzbl %al, (%edx)

位擴充套件

int

char

movb %al, (%edx)

截斷

unsigned

unsigned char

movb %al, (%edx)

截斷

unsigned

int

movl %eax, (%edx)

位模式重新解釋

reference: