開篇廢話
這幾天一直忙著積累知識,還沒有來得及總結(jié)呢,前些日子講述了一種在C語言環(huán)境中設(shè)置數(shù)組的對齊的方式,但是那個方式的演示是在IAR 的編程環(huán)境中給予支持的,對于icf文件(連接文件)在gcc中叫做ld文件,很多人都沒有接觸過,更不知道如何去設(shè)置段的方式進(jìn)行對齊。
正篇
還是上篇中講述的那個需求,在最近的某個月黑風(fēng)高的夜晚,睡覺之前的我突發(fā)奇想,想到一種另類的解決辦法,也就是套用結(jié)構(gòu)體的辦法去實現(xiàn)數(shù)組的首地址對齊方式。
需求:實現(xiàn)一個大數(shù)組 array_a[3874]的首地址在一個4字節(jié)或者8字節(jié)對齊的地址上。
首先,構(gòu)造一個簡單的結(jié)構(gòu)體:
struct test
{
char a[3874];
int b ;
};
使用C99/C++中支持的靜態(tài)初始化結(jié)構(gòu)體的辦法進(jìn)行賦值:
static struct test test1 = {
.a[3874] = {1,2,3,4...}, //C++ C99以上才支持這種賦值方式。
};
這樣子定義的數(shù)組a[3874]的首地址就是位于一個4字節(jié)對齊的地址上的。
如果要8字節(jié)對齊呢?將結(jié)構(gòu)體改為如下,初始化的方式同上即可。
struct test
{
char a[3874];
double b ;
};
為啥這樣子就可以了呢?
是這樣子的:
解釋如下
這里使用了一種結(jié)構(gòu)體字節(jié)對齊來解決了數(shù)組首地址對齊的問題:因為結(jié)構(gòu)體字節(jié)對齊滿足三個準(zhǔn)則
引用自cnblogs上一位大神(clover_toeic)的博客 文章名為《C語言字節(jié)對齊問題詳解
》這里不便提供具體鏈接,感興趣的朋友自行百度。
- 結(jié)構(gòu)體變量的首地址能夠被最寬基本類型成員大小所整除;
- 結(jié)構(gòu)體每個成員相對于結(jié)構(gòu)體首地址的偏移量(offset)都是成員大小的的整數(shù)倍,如有需要編譯器會在成員之間加上填充字節(jié);
- 結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍,如有需要,編譯器會在最末一個成員加上填充字節(jié);
上述解決辦法正是使用了第一個原則,比如第二個結(jié)構(gòu)體中:
struct test
{
char a[3874];
double b ;
};
可以看出該結(jié)構(gòu)體中最寬的基本類型成員是double,在32位機器中占用64bit也就是8Byte,所以我們的結(jié)構(gòu)體首部地址存在于一個8Byte對齊的地址上,而成員中的第一個 char a[3874],正好是從結(jié)構(gòu)體中首地址開始占用的,a[0]的地址就是結(jié)構(gòu)體的首地址;
總結(jié),此方法優(yōu)于之前提出的在鏈接文件中劃分塊的方式進(jìn)行對齊,因為這種方式不依賴編譯器,是一種通用的方法。
感謝
如果我的文章有哪里有錯的地方,勞煩讀者指出哈。如果覺得我的文章對您有用,那就麻煩回復(fù)我一下,表示有用。如果確實很有用,就請點一個喜歡,謝謝啦。