2012年4月14日 星期六

Alignment & Padding (English)

In order to prevent alignment exception, compiler will pad some empty data into memory to let it fit the alignment restriction.
Here is an example in C:

If we declare a structure like this:

struct align{
   char a;
   int b;
   short int c;
};

We will consider that it will use 7 bytes. However, because it has to prevent alignment exception,compiler will add some padding to let it fit 32-bit (i.e. 4 bytes). It may consider like this:

struct align{
   char a;
   char padding_0[3]; // add by compiler, programmer cannot use   
 
   int b;
   short int c;
   char padding_1[2]; // add by compiler, programmer cannot use   
};

Its memory allocation will look like this:
(放圖)

It is obvious to see that padding will waste lots of memory space. As a result, in order to save memory space, sometimes compiler also provide some pragma to let programmer to add in their code, and compiler can use these pragma to let compiler reallocate the memory allocation of this structure.

Here is an example:

#pragma pack(push)
#pragma pack(4)
        struct align
        {
                char a; //1 byte
                int b;  //4 bytes
                short int c;  //2bytes
        };
#pragma pack(pop)
It will let compiler to reallocate its memory allocation and use memory more efficiently.



Creative Commons Licence



Ref: http://en.wikipedia.org/wiki/Data_structure_alignment

About me

Junior System Software Programmer

M.S. in CS
B.S. in EE

In EECS area

Major research interest: Virtualization, Kernel
Minor research interest: Computer Architecture, Compiler, Other system software
More minor research interest: Digital Signal Process
Just for fun: Probability, Electromagnetism

Familiar develop environment:
Processor: ARM, x86, TI-C64xx;
OS: Linux, Mac OS X;
Compiler: GCC, Clang-LLVM

Preferred Software License: BSD License
Preferred Kernel: XNU ( Darwin Kernel )
Preferred Compiler: LLVM


於EECS領域研究興趣:
主要研究作業系統核心、虛擬化技術。對於計算機架構與其他系統軟體亦有相當的研究興趣。因過去大學時的經驗,對DSP、機率、電磁相關領域的知識,亦會作為業外新知來吸收。

熟悉的開發平台與環境:
在處理器架構上,主要對ARM有相對較高的熟悉,對x86、TI-C64xx系列亦有些微了解。在作業系統環境上,主要開發對象為Linux,主要使用環境為Mac OS X與Ubuntu。在編譯器環境上,傳統上使用GCC,最近亦對LLVM有興趣接觸與使用。

C語言:函式的Coding-style

傳統上,我們學C語言的時候,大多使用的寫法方式大多如下:
int main(int argc,char **argv)
{
 ... 
}

會直接把傳進函數的參數的type與名稱打在函式名稱右邊的小括弧中。

也因此,有些人的Coding-style,會傾向把函式的左括弧和函式名稱放在同一行,就例如這樣:
int main(int argc,char **argv) {
 ... 
}

這樣的寫法並不違背C語言的語法,拿去編譯器編譯也當然會過,說實在的如果只是寫給自己看、或是工作的環境並沒有特別指定Coding-style的話,只要自己習慣並沒有什麼不好。

然而,如果開發OpenSource相關專案的人,或多或少都會和開源社群交流,也會去trace甚至更改Source code,在這樣的狀況下,規範一個固定的Coding-style實屬必要。以Linux社群為例,就有著一份 "Documentation/CodingStyle and Beyond" (http://kernel.org/doc/ols/2002/ols2002-pages-250-259.pdf) 來約束大家的Coding-style,以便其他完全素昧平生的開發者,也能輕易的(?)看懂你寫的原始碼。

在"Documentation/CodingStyle"這篇文章當中,對函式寫法的標準是:
int foo(int x)
{
 ... 
}

一開始我在看到這段的時候,覺得只是一個換行符號的差別,僅是社群內自行約束的習慣而已,並不以為意。

然而,後來因緣際會看到一些特殊的函式寫法例子之後,就覺得將左括弧換行是有其必要性,我們來看一個例子:
int main(argc,argv)
    int argc;
    char **argv;
{
 ... 
}

上面的程式碼是在GNU Bash當中,實作printenv指令時,main function的寫法。從上面我們可以看到,他在函式名稱旁邊的小括弧當中,其傳遞進函式的參數,僅將其名字列出,並不指定type,而是換行之後才將其宣告寫入,最後再換行打入左大括號。

初次看到此種寫法之時,會以為這個寫法是有問題的,但將此種寫法拿去編譯器編譯,並不會出現問題,此種寫法是早期C語言的寫法,而在此寫法中,函式變數旁的小括弧和負責包住函式本體的大括弧中間,確實有可能出現其他內容,甚至有換行之必要,故在此寫法下,會希望負責包住函式本體的左大括弧,和括住傳入函式參數的小括弧中間有需要換行,而此習慣便延續到現在Linux kernel的Coding-style當中。



Creative Commons Licence