轉自:http://www.amobbs.com/thread-5465091-1-2.html
結構體與聯合體是C語言的常見數據類型,可對C的基本數據類型進行組合使之能表示複雜的數據結構,意義深遠,是優異代碼的必備工具。
一. struct與 union的基本用法,在語法上union與struct相同,因此只以struct爲例1.1 基本用法: 1.2 在聲明結構體的同時定義變量: 1.3 使用 typedef 來簡化struct的類型說明: 1.4 使用時尤其注意後面的分號,必不可少;
二. struct 與 union的區別
2.1 struct中的成員是按順序依次排列,互相獨立,在排列時引入了對齊問題(2.2);而union中的成員共用一塊內存,起始地址都是相同的,即union中的成員是對同一地址的多個引用、對同一地址的多種表達方法。
2.2 struct的對齊問題
對齊問題即struct中每個成員起始地址的分配。爲了可以快速訪問到每個成員,(以EW430爲例)編譯器根據成員的類型放到合適的地址上,默認爲2字節對齊。如:
Struct AA{char c; int d;}aa;
假設aa被分配在地址N上,並且N爲偶數,則aa.c的地址爲N,aa.d的地址爲N+2,而N+1地址未使用被浪費了。
對齊字節大小的指定:通過#pragma pack(n)來指定對齊字節的大小,n爲某些常量(EW430中可取1,2,4,8,16),指定以n字節對齊。通常使用編譯器默認的對齊大小最爲適宜。如果指定對齊大小爲1字節對齊,以上面的結構體變量aa爲例,aa.c地址爲N,aa.d地址爲N+1,是個奇數地址,因爲430在奇數地址只能讀取一個字節,因此要訪問d成員需要讀取兩次才能完成,後果是代碼變長、速度變慢。
三. 匿名結構體與聯合體
匿名結構體和聯合體,即沒有名字的結構體或者聯合體,這種結構體(或聯合體)無法通過.與->操作符引用(因爲它所屬的結構體或聯合體沒有名字,無法應用),而像暴露在外面一樣,與外層作用域相同,可直接使用。
3.1 C標準中提及的匿名結構體和聯合體(草稿原文引用)(C標準中提及的匿名結構(聯合)體應該只適用於有名結構體(聯合)中的匿名結構(聯合)體成員) 3.2 IAR中的匿名結構體和聯合體
IAR中的匿名結構體和聯合體可以具有全局作用域,因此結構體或聯合體中的成員可以作爲全局變量使用,但卻兼具結構體或者聯合體的屬性。
(1) IO430.h系列頭文件的寄存器聲明方式:
如:
說明:[1]. SFRIE1和SFRIE1_bit具有全局變量的性質,可以直接被引用。
[2]. SFRIE1和SFRIE1_bit在同一聯合體中,根據聯合體的性質,他們共享同一地址,即對同一寄存器不同訪問方式,SFRIE1對整個寄存器操作,SFRIE1_bit可對某位操作,如:
SFRIE1 |= 0x0001;和SFRIE1_bit.WDTIE = 1;具有相同效果。
[3]. 冒號(:)與整數稱之爲位域,使用位域表達的變量使用同一數據中的不同位,並按順序排列。整數表示這個變量佔用多少位。沒有名字的位域不能被引用到,一般用來保留未使用到的位(佔位作用)。
(2) 在應用程序中也可以使用此特性來實現一些功能。
記得某位網友曾提出過這樣的問題,要高效的使用一個整數的高8位和低8位,則可以用如下代碼解決: 或者 非常好的解決方案,只佔用一個整數的空間,可以對高8位、低8位、整個16位引用而不需要計算。
(3) 聯合體中的位域(補充) 結果:a = 1, b = 3, c = 7;
(4)結構體中的位域長度0 (補充) 長度爲0的位域是通知編譯器不要在以前的單元上分配位域了,代表着一個單元的位域分配結束,這個長度爲0的位域不能有名字。以後的位域分配要新開闢一個單元。
以上的例子中,z1, z2, z3, z4共用一個unsigned int中的4個bit,z6單獨使用一個unsigned int; 此結構體共佔用兩個unsigned int空間