類型轉換

1.不同類型數據間的混合運算與類型轉換:
①若參與運算量的類型不同,則先轉換成同一類型,然後進行運算
②轉換按數據長度增加的方向進行,以保證精度不降低。如int型和long型運算時,先把int量轉成long型後再進行運算
a、若兩種類型的字節數不同,轉換成字節數高的類型
b、若兩種類型的字節數相同,且一種有符號,一種無符號,則轉換成無符號類型
③所有的浮點運算都是以雙精度進行的,即使僅含float單精度量運算的表達式,也要先轉換成double型,再作運算
④char型和short型參與運算時,必須先轉換成int型
⑤在賦值運算中,賦值號兩邊量的數據類型不同時,賦值號右邊量的類型將轉換爲左邊量的類型。如果右邊量的數據類型長度左邊長時,將丟失一部分數據

2.C語言轉換規則:
(1)整數和浮點型:
浮點型轉換成整型時,小數部分被省略,如果其值不能被整型表示,則其行爲未定義。注意:將負的浮點型轉換成unsigned int 結果是沒有定義的。
當把整型轉換成浮點型時,如果該值是在可表示範圍內,則結果可能是下一個較高或者較低的可表示值。如果結果在範圍外,則行爲未定義。
(2)浮點型:
將較低精讀浮點型轉換成較高浮點型時:值不變。
將較高精度轉換成較低精度時:在範圍內,值不變,在範圍外,結果爲定義
(3)整型提升:
如果原始類型都可以用int表示,則將其轉換成int,否則被轉換成unsigned int
(4)整型轉換:
將unsigned 轉換成 signed 時,如果可以在新類型表示,則表示,如果不能表示,結果與具體實現有關,將signed 轉換成unsigned時,若unsigned位數窄,對二進制補碼進行左截取,若unsigned寬,對signed進行符號擴展。
(5)指針和整數:
指針可加上或着減去一個整數,轉換規則按照加法運算符號方式進行,兩個指向同一數組的指針可進行加減運算,方式按照算數轉換規則,值爲0的整型常量或者void*型表達式可轉換成任意類型的指針,指針可以轉換成整型,注意整型必須足夠大,整型對象可以轉換成指針,一般用於將一個足夠寬的從指針轉換來的整型轉換成(恢復)指針,不同類型的指針間可以相互轉換,但必須滿足內存對齊條件,一個指針可以轉換成同意類型的另一個指針,但是可以增加或者刪除另一個指針的限制符,如果和另一個指針,增加了相同的修飾符,則和另一個指針一樣,如果刪除了修飾符,則底層對象的運算仍受到原聲明的限制。

3.如果沒有unsigned類型的操作數,則只要使用下面這些非正式的規則就可以了:
若其中一個爲long double,則將另一個轉換成long double型
若其中一個爲double,則將另一個轉換成double
若其中一個爲float,則將另一個轉換成float
將 char和short 轉換成 int
若其中一個爲long,將另一個轉換成long
當包含unsigned時,轉換規則複雜一些

4.
1) 符號擴展:對於要擴展量爲有符號數,擴展存儲位數的方法。在新的高位字節使用當前最高有效位即符號位的值進行填充。

例1:

    char a=0xff;//有符號值爲-1,二進制爲11111111,其中最高位爲符號位

    shortb=a;//b的有符號值爲-1,在內存中存儲的值爲1111111111111111

例2:

    char a=1;//有符號值爲1,二進制爲00000001,其中最高位爲符號位

 shortb=a;//b的有符號值爲1,在內存中存儲的值爲0000000000000001

2) 零擴展:對於要擴展量無符號數,擴展存儲位數的方法。在新的高位直接填0.

例1:

unsigned char a=0xff;//二進制爲11111111,所有值都是有效值

unsigned short b=a;//b經過零擴展後,內存中存儲的值爲0000000011111111

幾個例子看下來,但還有兩種情況沒有涉及到,一是有符號短變量擴展成無符號長變量;二是無符號短變量擴展成有符號長變量。這兩種情況編譯器該怎麼處理呢?

其實這裏注重的是要擴展的量是有符號量還是無符號量。若要擴展量爲有符號量,不管擴展成有符號還是無符號,都遵循符號擴展;若要擴展量爲無符號量,不管擴展成有符號還是無符號,都遵循零擴展。

例1:

    char a =0xff;//a爲-1,其爲有符號量,二進制爲11111111

    unsigned shortb=a;//此處a要進行符號擴展,b的二進制爲11111111 11111111

例2:

    unsigned chara=0xff;//a爲無符號量,二進制爲11111111

    short b=a;//此處a要進行零擴展,b的二進制爲00000000 11111111

2)類型轉換和擴展:

1)、短數據類型擴展爲長數據類型

i.要擴展的短數據類型爲有符號數的

進行符號擴展,即短數據類型的符號位填充到長數據類型的高字節位(即比短數據類型多出的那一部分),保證擴展後的數值大小不變

1:char x=10001001b; short y=x; 則y的值應爲11111111 10001001b;

2:charx=00001001b; short y=x; 則y的值應爲00000000 00001001b;

ii. 要擴展的短數據類型爲無符號數的

進行零擴展,即用零來填充長數據類型的高字節位

1:unsignedchar x=10001001b; short y=x; 則y的值應爲00000000 10001001b;

2:unsignedchar x=00001001b; short y=x; 則y的值應爲00000000 00001001b;

2)、長數據類型縮減爲短數據類型

如果長數據類型的高字節全爲1或全爲0,則會直接截取低字節賦給短數據類型;如果長數據類型的高字節不全爲1或不全爲0,則轉會就會發生錯誤。

3)、同一長度的數據類型中有符號數與無符號數的相互轉化

直接將內存中的數據賦給要轉化的類型,數值大小則會發生變化。另短類型擴展爲長類型時,但短類型與長類型分屬有符號數與無符號數時,則先按規則一進行類型的擴展,再按本規則直接將內存中的數值原封不動的賦給對方

2、 數組變量及其成員

由於數組名是常量,不能用數組名賦給另一個數組名,如下的情況是不被允許的:

               int a[10]={1,2,3,4,5,6,7,8,9,10},b[10]={11,12,13,14,15,16,17,18,19,20};

               a=b;//這是不被允許的,因爲a,b都是常量,常量不允許被改變

注意在數組定義聲明時,編譯器就會給它分配了空間。數組名爲該空間的首地址。

雖然數組名不能直接賦值,但是數組成員可以直接賦值和計算,規則遵循前面提到的“基本類型變量轉換”,例如:

               int a[10]={1,2,3,4,5,6,7,8,9,10};

               a[3] = 16;

也可以這樣:

               *(a+3)=16;//這也是後面要說的

3、 結構、聯合和枚舉變量及其成員變量

同類型的結構可以相互賦值,例如

typedef struct test{

               char*name;

               unsignedshort age;

} Struct_test;

Struct_test a,b={“zhangsan”,20};

a = b;//a和b中的數據是一樣的,但在不同的存儲空間

a.name=”lisi”;//結構中的成員賦值

                        a.age = 25;

                        b.age = a.age;



                        在此,特別介紹一下,通過成員變量來獲取到結構的首地址的方法:

                        先定義一個宏來確定該成員在結構中的偏移量

                        #define offsetof(type,name) (size_t)((char *)&((type *)0)->name – (char *)(type *)0)

                        size_t offset =offsetof(Struct_test, age);

                        Struct_test test ;

                        If((char *)&test==(char*)&test.age-offset){

                                 printf(“structureaddr!\n”);

}

下面在介紹一下,通過共用體來確定機器是大端序還是小端序的例子:

include

發佈了20 篇原創文章 · 獲贊 22 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章