c語言struct字節(jié)對(duì)齊 結(jié)構(gòu)體成員的字節(jié)對(duì)齊?
結(jié)構(gòu)體成員的字節(jié)對(duì)齊?這個(gè)問題非常嚴(yán)重。首先,我想說的是字節(jié)對(duì)齊的語法在不同的編譯器下是不同的。在GCC中,它是#pragmapush(1)#pragmapack(),在MSC VC中的代碼項(xiàng)可以調(diào)整
結(jié)構(gòu)體成員的字節(jié)對(duì)齊?
這個(gè)問題非常嚴(yán)重。首先,我想說的是字節(jié)對(duì)齊的語法在不同的編譯器下是不同的。在GCC中,它是#pragmapush(1)#pragmapack(),在MSC VC中的代碼項(xiàng)可以調(diào)整,默認(rèn)為8字節(jié);typestruct{charcinti}test byte alignment,是alignment,例如char和int是4字節(jié)對(duì)齊的,那么char會(huì)占用4字節(jié),一共8字節(jié),結(jié)構(gòu)對(duì)象存儲(chǔ)是按順序存儲(chǔ)的,char必須在int前面。在第二種情況下,如果一個(gè)字節(jié)對(duì)齊,則表示char只占用一個(gè)字節(jié),而int將占用四個(gè)字節(jié)。這種n字節(jié)對(duì)齊意味著每個(gè)成員占用的空間必須是n字節(jié)的倍數(shù),小于n字節(jié)的占用n字節(jié)。所以把它和一個(gè)字節(jié)對(duì)齊,它需要五個(gè)字節(jié)。此外,根處理器與您提到的每種數(shù)據(jù)類型的低位還是高位在前面有關(guān)。Intel處理小型端對(duì)齊。例如,整數(shù)522387969用十六進(jìn)制表示為:0x1f230201,在英特爾處理器中表示為0x0102231f,因此內(nèi)存使用0x0102031f來表示522387969,這稱為小端對(duì)齊。但在arm處理器中,522387969表示為0x1f230201,這被稱為大端對(duì)齊,也被稱為網(wǎng)絡(luò)字節(jié)順序。當(dāng)然,上面提到的字節(jié)順序只對(duì)內(nèi)置數(shù)據(jù)類型(如intlongshort)有效。如果結(jié)構(gòu)中有intlong這樣的成員,那么也會(huì)有所謂的字節(jié)順序。如上所述,無論順序是什么,結(jié)構(gòu)對(duì)象都是按順序存儲(chǔ)的。首先定義的成員必須在后面定義的成員之前,但單個(gè)成員具有字節(jié)順序。我不知道怎么說明白嗎?不,請(qǐng)仔細(xì)理解這句話:n字節(jié)對(duì)齊意味著每個(gè)成員占用的空間必須是n字節(jié)的倍數(shù),小于n字節(jié)的占用n字節(jié)。如果大于n字節(jié),它將構(gòu)成n字節(jié)的倍數(shù)。例如,如果按3字節(jié)對(duì)齊,則4字節(jié)int將占用6字節(jié)。對(duì)齊與數(shù)據(jù)在內(nèi)存中的位置有關(guān)。如果變量的內(nèi)存地址是其長度的整數(shù)倍,則稱為自然對(duì)齊。例如,在32位CPU中,如果整數(shù)變量的地址是0x00000004,則它自然對(duì)齊。字節(jié)對(duì)齊的根本原因是CPU訪問數(shù)據(jù)的效率。假設(shè)上面整數(shù)變量的地址不是自然對(duì)齊的,例如0x00000002,那么CPU需要訪問內(nèi)存兩次,如果它接受它的值。第一次從0x00000002-0x00000003取短,第二次從0x00000004-0x00000005取短,然后合并得到所需的數(shù)據(jù)。如果變量的地址為0x00000003,則需要訪問內(nèi)存三次,第一次訪問char,第二次訪問簡稱char,第三次訪問char,然后合并得到整數(shù)數(shù)據(jù)。如果變量處于自然對(duì)齊位置,則只能檢索一次數(shù)據(jù)。有些系統(tǒng)對(duì)對(duì)齊非常嚴(yán)格,如SPARC系統(tǒng)。如果獲取未對(duì)齊的數(shù)據(jù),則會(huì)發(fā)生錯(cuò)誤。例如,char ch[8]char*P=& ch[1]int i=*(int*)P在運(yùn)行時(shí)會(huì)報(bào)告為段錯(cuò)誤,而X86上不會(huì)有錯(cuò)誤,但效率會(huì)降低。
結(jié)構(gòu)體字節(jié)對(duì)齊原則?
目前算法工程師的分工比較詳細(xì),而且很多算法工程師不做算法實(shí)現(xiàn),所以在使用編程語言時(shí)可能會(huì)出現(xiàn)不熟悉的情況。但是現(xiàn)在很多程序員對(duì)基礎(chǔ)知識(shí)的掌握不如以前那么扎實(shí),這是一個(gè)明顯的現(xiàn)象。
作為面試官,我經(jīng)常參加一些企業(yè)的程序員面試。在面試中,我通常會(huì)問一些基本的問題來了解程序員的基本知識(shí)結(jié)構(gòu)。例如,我問了一個(gè)問題,int是幾個(gè)字節(jié),大多數(shù)程序員都能回答這個(gè)問題。類似的問題包括計(jì)算機(jī)端口號(hào)的范圍、網(wǎng)絡(luò)尋址方式、TCP協(xié)議與UDP協(xié)議的區(qū)別、接口的作用、異或操作的規(guī)則等。一般來說,這些問題通常是由初級(jí)程序員提出的,而對(duì)于高級(jí)程序員,他們通常會(huì)被問到一些具體的解決方案。
一些簡單的基本問題的答案可以反映程序員的基本知識(shí)結(jié)構(gòu)。根據(jù)歷史經(jīng)驗(yàn),一些非計(jì)算機(jī)專業(yè)的程序員可能很難回答這些問題,因?yàn)槟壳昂芏嗑幊陶Z言都比較簡單,在很多實(shí)驗(yàn)中都無法實(shí)踐這些基礎(chǔ)知識(shí),但是這些基礎(chǔ)知識(shí)還不夠,知識(shí)對(duì)程序員來說更重要。
在許多情況下,即使你不回答一些基本問題,也不要泄氣。畢竟,目前的發(fā)展環(huán)境與早些年大不相同。程序設(shè)計(jì)更加注重模塊化、可擴(kuò)展性等問題。但是程序員必須掌握基本知識(shí),特別是一些常識(shí)性問題。
我已經(jīng)使用Java、C和python很長時(shí)間了,我還在頭條上繼續(xù)寫一些關(guān)于編程和大數(shù)據(jù)的文章。對(duì)這些內(nèi)容感興趣的人可以關(guān)注我,我相信他們會(huì)有所收獲。
謝謝!