c語言裏的簡單類型只有兩類,整數型 和浮點型:
整數型: char 1
short 2
int 4
long 4
浮點型 :float 4
double 8
C語言裏並沒有規定short int 和 long各自佔都少個字節,他們只要求滿足下面的關係:
short佔用空間《= int 佔用空間 《= long 佔用空間
而按照約定,int 的大小一般剛好佔用一個機器字節,所以就有了上述的結果。
問題就有了,如果不同類型之間相互賦值,C語言是如何處理的??
#1,相同種類變量(同時整型或者浮點型)之間相互賦值:
當然float 和double之間的賦值大家都很清楚,float賦值double可以,但是反過來就會丟失精度。
我今天想說的重點是char 和 int 之間:(尤其是作嵌入式平臺容易出現錯誤)
首先,我們都知道整型有signed 和unsigned之分。
當你寫 :char c; 實際上是 signed char c; 佔用一個字節
char c =0x80;
int i= c;
這是 i的值竟然是-128.下面是在centos上調試的結果:
#include <stdio.h>
int main(void)
{
char c=0x80;
int i=c;
printf("i=%d.\n",i);
return 0;
}
編譯運行的結果:
[adminiter@trageday bolg]$ gcc 02.c
[adminiter@trageday bolg]$ ./a.out
i=-128.
爲啥會這樣呢?
因爲c是signed char ,而0x80(二進制表示是:1000_0000)最高位是‘1’,所以C 是負數,(帶符號)擴展成32位變成0xFFFF_FF80,把這個賦值給i,i當然就是負數了。
但如果這樣寫:
unsigned char c=0x80;
int i=c;
這是i就是128.
在據一個例子:
int i=5;
int u=i;
這個賦值是肯定沒有問題的,
但是:
int i=5;
unsigned u=i;
就有可能出現問題,是可能啊。例:
int i=-5;
unsigned u=i;
u的結果是多少呢?
u=4294967291.
原因和上面個那個差不多,首先編譯器把-5轉換成二進制0xFFFF_FFFB 賦值給了i,然後把 i的值賦值給了u,所以最後u仍然等於0xFFFF_FFFB。值還是那個值,但是有u的(unsigned)解釋出來就是4294967291。
這就是C語言對賦值的處理。只是簡單的符號擴展(有符號)然後把二進制拷貝,然後使用對方的“格式”解釋。當然,佔內存不同的類型之間會存在空間取捨。
複合類型:
C語言提供了幾種複合類型:struct(結構體),union(共用體)和bit field (位域)。結構體和共用體使用的組多的,這裏我就不重複它們的使用方法,只討論幾個有意思的問題(關於內存對齊的問題)alignment(對齊)
例:
#include <stdio.h>
struct s
{
char c;
int i;
};
int main(void)
{
printf("sizeof(struct s)=%d.\n",sizeof(struct s));
return 0;
}
運行調試結果如下:
[adminiter@trageday bolg]$ gcc 02.c
[adminiter@trageday bolg]$ ./a.out
sizeof(struct s)=8.
解釋這個之前,我們要了解alignment(對齊)的概念。
CPU對內存的訪問並不是完全任意的,如果CPU相一次讀(寫)4個字節,那給出的內存地址最好是4的倍數,例如:
0x12345670
0x12345674
0x12345678
0x1234567c
十六進制下,最低位一定是0 ,4 , 8,c 這樣四的倍數結尾的,CPU只需要通過一次訪問就可以得到完整的數據。否則,CPU就要通過多次操作才能完成一次完整的存取。例如:
我們要求CPU從0x12345672 讀取4個自己到寄存器,CPU只能這樣做:
第一步,從0x12345670讀4個字節,捨棄掉16位數據,把剩下的高16位存起來。
第二步 , 從0x12345674讀4個字節,捨棄掉16位數據,和上一次取的數據共同組成32位要取的數據。
可以看出,如果不對數據做出特別的安排,CPU對數的訪問就會缺乏效率。爲了提高效率,編譯器一般都會把數據放到合適自己的位置上。譬如,int 佔4字節,所以int變量的地址都是4的倍數,這個就稱作 “4字節對齊”。
所以我們平時寫結構體時應該注意點字節對齊問題,如:
struct s
{
char x;
int y;
char z;
int u;
};
結構體s 佔用16字節。
struct s1
{
int y;
int u;
char x;
char z;
};
結構體s1 佔用12字節。
還有一個值得注意的問題:
這個結構體佔用多少字節呢?
struct s
{
int y;
char z;
};
可能有人說是5字節,一個4字節對齊,一個1字節對齊。共5字節。X X X X X X X X
其實正確答案是8字節。
原因和上面的差不多,還是數據對齊的緣故。試想下,如果我寫個:
struct s array【10】;
則array是由10個s組成的,這10個s必須依次安排在一塊連續的區域。那樣的話,如果s佔用5個字節,問題就是array【0】還可以,但是array【1】的字節就不是對齊的了。後面的就更是亂套的。
所以最後整個結構體還要按照數據成員佔內存最大的成員進行對齊。按上面例子就是 :
5字節數據 按4字節對齊存儲,就是8個字節。
如有錯誤,請指出來。謝謝