c語言位元組對其問題

2021-08-17 14:21:55 字數 1693 閱讀 6286

最近除錯網路的服務端程式,自己寫了乙個小客戶端程式來測試,發現服務程式解包錯誤。經除錯發現客戶端的協議頭大小和伺服器端的協議頭大小不一致。原因是伺服器端加了#pragma pack(1),而客戶端沒加。

之前沒接觸過這個編譯巨集,現在來認真學習之。

首先google之~~

原來#pragma pack有幾種形式,我所接觸到的是#pragma pack(n),即變數以n位元組對齊。

變數對齊在每個系統中是不一樣的,預設的對齊方式能有效的提高cpu取指取數的速度,但是可能會浪費一定的空間。在網路程式中採用#pragma pack(1),即變數緊縮,

不但可以減少網路流量,還可以相容各種系統,不會因為系統對齊方式不同而導致解包錯誤。

了解了概念和優點,現在我們就來測試之~

平台:cpu—pentium e5700 記憶體—2g

1.作業系統:

ubuntu 11.04 32bit   

編譯器:g++ 4.5.2

2.作業系統:windows xp

編譯器:vs2010

先看第乙個測試。

結構體在正常情況和緊縮情況在以上不同環境下占用的記憶體大小。

1struct

pack 

測試結果為:

1:2:

測試結果分析:

可以看出緊縮後結構體的大小為15,是結構體內置型別大小的和。但是在預設情況下,結構體的大小都是對齊位元組數的倍數。ubuntu下pack只需要20個位元組,而windows要24個位元組。這是因為ubuntu是以4位元組對齊,而windows則是以最大的內建型別的位元組數對齊,在結構體內最大的內建型別為double,其大小為8個位元組。他們在記憶體中的對齊方式如下圖:

1:2:

還需注意的是,

在對齊型別的內部都是以

2位元組對齊的。

結論:在預設情況下,

linux

作業系統是以

4位元組對齊,

windows

作業系統則是以最大的內建型別對齊。

第二個測試

乙個結構體內包含另外乙個結構體,其大小的情況。

內部的結構體為

1struct

pack 

外部的結構體為

1struct

complex _pack;

我們有四種情況:

1.pack

緊縮,complex _pack

緊縮2.

pack

緊縮,complex _pack

預設3.

pack

預設,complex _pack

緊縮4.

pack

預設,complex _pack

預設以下的排列均按此順序。

測試的結果

1:2:

測試結果分析:

在兩個作業系統下,除了第一種情況----內結構體和外結構體都緊縮----相同之外,其他三種情況都不相同。我們可以根據偏移畫出結構體在記憶體中的情況。第一種情況省略。

1:2:

結論:#pragma pack只影響當前結構體的變數的對齊情況,並不會影響結構體內部的結構體變數的排列情況。或者說

#pragma pack

的作用域只是一層

。我們由第三種情況,內部結構體正常,外部結構體緊縮,可以得出結構體的對齊是按偏移計算的。

這裡還有乙個問題沒解決,為什麼第二種情況內部結構體的偏移都是1?不是4或者8?

C 語言中結構體位元組對其的兩種方式

c語言中位元組對其有兩種方式 1 通過預處理命令 pragma pack n 指定按照n位元組對齊 pragma pack 取消自定義的對齊值 例如 pragma pack 2 struct a struct b pragma pack 2 attribute packed 取消結構體在編譯過程中的...

c語言位元組對齊問題(一)

在這裡只總結結構體的位元組對齊問題,看下面的結構體 struct s1 char a int b short c struct s2 char a short c int b 那麼sizeof s1 12,sizeof s1 8 我們可以假定結構體在記憶體中的位址是0x0000開始的,那麼我們說的位...

c語言位元組對齊問題(二)

struct s 那麼sizeof s 4 先說下位域在記憶體對齊的一些規則 2.位域的多少定義多少就後面接多少位,但是位域要求是連續的位元組,像a已經占有4位了,乙個位元組8位,那麼就會填補4位,到下個位元組,所以到b變數占用的是另個一新位元組。3.對於一些資料說位域不能跨兩個位元組,就是說位域長...