項目之IC卡芯片3

項目之IC卡芯片3


題目:

 struct A
{
char t:4;
char k:4;
unsigned short i:8;
unsigned long m;
}
sizeof(A)=?(不考慮邊界對齊)

7,如果考慮邊界對其,則爲8

 

以下段落引用來源:http://daixinghe.blog.163.com/blog/static/18436159201062111032307/

有些信息在存儲時,並不需要佔用一個完整的字節, 而只需佔幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。爲了節省存儲空間,並使處理簡便,C語言又提供了一種數據結構,稱爲“位域”或“位段”。所謂“位域”是把一個字節中的二進位劃分爲幾個不同的區域,並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。這樣就可以把幾個不同的對象用一個字節的二進制位域來表示。一、位域的定義和位域變量的說明位域定義與結構定義相仿,其形式爲: 
struct 位域結構名 
{ 位域列表 }; 
其中位域列表的形式爲: 類型說明符 位域名:位域長度 
例如: 
struct bs 

int a:8; 
int b:2; 
int c:6; 
}; 
位域變量的說明與結構變量說明的方式相同。 可採用先定義後說明,同時定義說明或者直接說明這三種方式。例如: 
struct bs 

int a:8; 
int b:2; 
int c:6; 
}data; 
說明data爲bs變量,共佔兩個字節。其中位域a佔8位,位域b佔2位,位域c佔6位。對於位域的定義尚有以下幾點說明: 
1. 一個位域必須存儲在同一個字節中,不能跨兩個字節。如一個字節所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如: 
struct bs 

unsigned a:4 
unsigned :0 /*空域*/ 
unsigned b:4 /*從下一單元開始存放*/ 
unsigned c:4 

這個位域定義中,a佔第一字節的4位,後4位填0表示不使用,b從第二字節開始,佔用4位,c佔用4位。 
2. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如: 
struct k 

int a:1 
int :2 /*該2位不能使用*/ 
int b:3 
int c:2 
}; 
從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。
簡而言之,言而簡之
這是位域操作的表示方法,也就是說後面加上“:1”的意思是這個成員的大小佔所定義類型的1 bit,“:2”佔2 bit,依次類推。當然大小不能超過所定義類型包含的總bit數。 
一個bytes(字節)是8 bit(bit)。例如你的結構中定義的類型是u_char,一個字節,共8bit,最大就不能超過8。 
32位機下, 
short是2字節,共16bit,最大就不能超過16. 
int是4字節,共32bit,最大就不能超過32. 
依次類推。 
這樣定義比較省空間。例如你上面的結構,定義的變量類型是u_char,是一字節類型,即8bit。 
fc_subtype佔了4bit,fc_type佔2bit,fc_protocol_version佔2bit,共8bit,正好是一個字節。 
其他八個成員,各佔1bit,共8bit,正好也是一個字節。 
因此你的結構的大小如果用sizeof(struct frame_control)計算,就是2bytes.


--------------------------------------------------------------------------------------------

結構體中的冒號
   今天看CRC的bit型算法學到了C++中的結構體定義可以使用":",具體說明如下:
在標準C語言中,下面的語句是合法的:
        struct test{
                int a:3;
        };
這樣定義的 a 在賦值後只取最後的3bit,即轉換爲 -4 到 3 之間的數值。比如:

賦值 -5 -4 -3 -2 2 3 4 5
實際值 3 -4 -3 -2 2 3 -4 -3

如果 a 爲無符號型,則會轉換爲 0 到 7 之間。且同樣適用於非 int 的其他類型(只是“:”後面的數和顯示 a 的結果時一定要是整型)。
其中賦值'-5(dec)'=1101(原)=1011(補),所以在進行取後3位操作後變成'3(dec)',當然在CRC運算的結構體定義中,肯定是只用到了最後一位,具體定義如下:
typedef unsigned char bit;
typedef unsigned char byte;
typedef unsigned short u16;
   
typedef union {
    u16 val;
    struct {
        u16 bit0 : 1;
        u16 bit1 : 1;
        u16 bit2 : 1;
        u16 bit3 : 1;
        u16 bit4 : 1;
        u16 bit5 : 1;
        u16 bit6 : 1;
        u16 bit7 : 1;
        u16 bit8 : 1;
        u16 bit9 : 1;
        u16 bit10 : 1;
        u16 bit11 : 1;
        u16 bit12 : 1;
        u16 bit13 : 1;
        u16 bit14 : 1;
        u16 bit15 : 1;
    } bits;
} CRCREGS;
PS:以後我儘量把自己學習的心得體會寫上來,免得以後忘了:)當然一些邏輯設計的電路圖實在不好畫的,我就寫在NOTEBOOK上面了。。。


位域是指信息在存儲時,並不需要佔用一個完整的字節, 而只需佔幾個或一個二進制位。例如在存放一個開關量時,只有0和1 兩種狀態, 用一位二進位即可。爲了節省存儲空間,並使處理簡便,C語言又提供了一種數據結構,稱爲“位域”或“位段”。所謂“位域”是把一個字節中的二進位劃分爲幾 個不同的區域, 並說明每個區域的位數。每個域有一個域名,允許在程序中按域名進行操作。 這樣就可以把幾個不同的對象用一個字節的二進制位域來表示。

位域的定義和位域變量的說明
位域定義
與結構定義相仿,其形式爲:

struct 位域結構名

{ 位域列表 };

其中位域列表的形式爲: 類型說明符 位域名:位域長度

例如:

struct bs

{int a:8;int b:2;int c:6;};
位域變量的說明
與結構變量說明的方式相同。 可採用先定義後說明,同時定義說明或者直接說明這三種方式。例如:

struct bs

{int a:8;int b:2;int c:6;}data;

說明data爲bs變量,共佔2個字節。其中位域a佔8位,位域b佔2位,位域c佔6位。
位域定義的幾點說明
對於位域的定義尚有以下幾點說明:

1. 寬度爲 0 的一個未命名位域強制下一位域對齊到其下一type邊界,其中type是該成員的類型。例如:

struct bs {

unsigned a:4;

unsigned :0 ;/*空域*/

char b:4 ;/*從下一單元開始存放*/

unsigned c:4;

}data;

VC6(默認的配置,未作任何優化選擇) 對空域的處理。

實驗中,0x0012ff74爲變量data的起始地址,位域a填充0x0012ff74的後四位,位域b從0x0012ff78開始,佔據0x0012ff78的後四位。所以空域佔據了從a開始的4個位剩餘部分。

乍看 VC6對空域的處理是依據空域的類型,即unsigned。其實不然。

經試驗,空域所佔大小和 a的類型及 空域的類型 二者皆相關。

即以下四種情況,

a,空域皆爲char時,二者共佔據1字節;

a 爲unsigned,空域爲unsigned; a 爲char,空域爲unsigned; a 爲unsigned,空域爲char;這三種情況,二者共佔據4字節。

2. 位域的長度不能大於指定類型固有長度,比如說int的位域長度不能超過32,bool的位域長度不能超過8。

3. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:

struct k

{int a:1int :2 /*該2位不能使用*/int b:3int c:2};

從以上分析可以看出,位域在本質上就是一種結構類型, 不過其成員是按二進位分配的。

位域的使用及佔用空間

位域的使用
位域的使用和結構成員的使用相同,其一般形式爲: 位域變量名·位域名 位域允許用各種格式輸出。

int main(void)

{

struct bs

{

unsigned a: 1;

unsigned b: 3;

unsigned c: 4;

}bit, *pbit;

bit.a = 1;

bit.b = 7;

bit.c = 15;

printf("%d,%d,%d\n", bit.a, bit.b, bit.c);

pbit = &bit;

pbit->a = 0;

pbit->b &= 3;

pbit->c |= 1;

printf("%d,%d,%d\n", pbit->a, pbit->b, pbit->c);

return 0;

}

上例程序中定義了位域結構bs,三個位域爲a,b,c。說明了bs類型的變量bit和指向bs類型的指針變量pbit。這表示位域也是可以使用指針的。

程序的9、10、11三行分別給三個位域賦值。( 應注意賦值不能超過該位域的允許範圍)程序第12行以整型量格式輸出三個域的內容。第13行把位域變量bit的地址送給指針變量pbit。第14行用指針
方式給位域a重新賦值,賦爲0。第15行使用了複合的位運算符"&=", 該行相當於:
pbit->b=pbit->b&3位域b中原有值爲7,與3作按位與運算的結果爲3(111&011=011,十進制值爲
3)。同樣,程序第16行中使用了複合位運算"|=", 相當於: pbit->c=pbit->c|1其結果爲15。程序第17行用指針方式輸出了這三個域的值。

爲了節省空間,可以把幾個數據壓縮到少數的幾個類型空間上,比如需要表示二個3位二進制的數,一個2位二進制的數,則可以用一個8位的字符表示之。

struct

{char a : 3;char b : 3;char c : 2;} ;

這個結構體所佔空間爲一個字節,8位。節省了空間。
位域的對齊
如果結構體中含有位域(bit-field),那麼VC中準則是:

1) 如果相鄰位域字段的類型相同,且其位寬之和小於類型的sizeof大小,則後面的字段將緊鄰前一個字段存儲,直到不能容納爲止;

2) 如果相鄰位域字段的類型相同,但其位寬之和大於類型的sizeof大小,則後面的字段將從新的存儲單元開始,其偏移量爲其類型大小的整數倍;

3) 如果相鄰的位域字段的類型不同,則各編譯器的具體實現有差異,VC6採取不壓縮方式(不同位域字段存放在不同的位域類型字節中),Dev-C++和GCC都採取壓縮方式;

系統會先爲結構體成員按照對齊方式分配空間和填塞(padding),然後對變量進行位域操作。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章