程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 實例講授C說話編程中的構造體對齊

實例講授C說話編程中的構造體對齊

編輯:關於C++

實例講授C說話編程中的構造體對齊。本站提示廣大學習愛好者:(實例講授C說話編程中的構造體對齊)文章只能為提供參考,不一定能成為您想要的結果。以下是實例講授C說話編程中的構造體對齊正文


Q:關於構造體的對齊,究竟遵守甚麼准繩?
A:起首先不評論辯論構造體按若干字節對齊,先看看只以1字節對齊的情形:

#include <stdio.h>
#include <string.h>

#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct,member) ((char *)&((struct *)0)->member - (char *)0)

#pragma pack(1)

typedef struct
{
  char  sex;
  short  score;
  int   age;
}student;

int main()
{
  PRINT_D(sizeof(student))
  PRINT_D(OFFSET(student,sex))
  PRINT_D(OFFSET(student,score))
  PRINT_D(OFFSET(student,age))
  return 0;
}

輸入:

sizeof(student) is 7
OFFSET(student,sex) is 0
OFFSET(student,score) is 1
OFFSET(student,age) is 3

可以看到,假如按1字節對齊,那末構造體外部的成員慎密分列,sizeof(char) == 1, sizeof(short) == 2, sizeof(int) == 4.

修正下面的代碼, 去失落#pragma pack語句,代碼以下:

#include <stdio.h>
#include <string.h>

#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct,member) ((char *)&((struct *)0)->member - (char *)0)

typedef struct
{
  char  sex;
  short  score;
  int   age;
}student;

int main()
{
  PRINT_D(sizeof(student))
  PRINT_D(OFFSET(student,sex))
  PRINT_D(OFFSET(student,score))
  PRINT_D(OFFSET(student,age))
  return 0;
}

運轉成果:

sizeof(student) is 8
OFFSET(student,sex) is 0
OFFSET(student,score) is 2
OFFSET(student,age) is 4

此時,各個成員之間就不像之前那樣慎密分列了,而是有一些裂縫。這裡須要引見下對齊准繩:

此准繩是在沒有#pragma pack語句感化時的准繩(分歧平台能夠會有分歧):

准繩A:struct或許union的成員,第一個成員在偏移0的地位,以後的每一個成員的肇端地位必需是以後成員年夜小的整數倍;

准繩B:假如構造體A含有構造體成員B,那末B的肇端地位必需是B中最年夜元素年夜小整數倍地址;

准繩C:構造體的總年夜小,必需是外部最年夜成員的整數倍;

根據下面3個准繩,我們來詳細剖析下: sex在偏移0處,占1字節;score是short類型,占2字節,score必需以2的整數倍為肇端地位,所以它的肇端地位為2; age為int類型,年夜小為4字節,它必需以4的整數倍為肇端地位,由於後面有sex占1字節,填充的1字節和score占2字節,地址4曾經是4的整數倍,所以age的地位為4.最初,總年夜小為4的倍數,不消持續填充。

持續修正下面的代碼,增長#pragma pack語句:

#include <stdio.h>
#include <string.h>

#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct, member) ((char *)&((struct *)0)->member - (char *)0)

#pragma pack(4)

typedef struct
{
  char  sex;
  short  score;
  int   age;
}student;

int main()
{
  PRINT_D(sizeof(student))
  PRINT_D(OFFSET(student,sex))
  PRINT_D(OFFSET(student,score))
  PRINT_D(OFFSET(student,age))
  return 0;
}

運轉成果:

sizeof(student) is 8
OFFSET(student,sex) is 0
OFFSET(student,score) is 2
OFFSET(student,age) is 4

詳細剖析下:

有了#pragma pack(4)語句後,之前說的准繩A和C就不實用了。現實對齊准繩是本身對齊值(成員sizeof年夜小)和指定對齊值(#pragma pack指定的對齊年夜小)的較小者。順次准繩,sex仍然偏移為0, 本身對齊值為1,指定對齊值為4,所以現實對齊為1; score成員本身對齊值為2,指定對齊值為4,現實對齊為2;所之前面的sex前面將填充一個1字節,然後是score的地位,它的偏移為2;age本身對齊值為4,指定對齊為4,所以現實對齊值為4;後面的sex和score正好占用4字節,所以age接著寄存;它的偏移為4.

Q:關於位域的成績,空域究竟表現甚麼?
A:它表現以後的位域重新空間開端。

#include <stdio.h>
#include <string.h>

#define PRINT_D(intValue)   printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct, member) ((char *)&((struct *)0)->member - (char *)0)

typedef struct 
{
  int a : 1;
  int b : 3;
  int : 0;
  int d : 2;
}bit_info;

int main()
{
  PRINT_D(sizeof(bit_info))
  return 0;
}

運轉成果:

sizeof(bit_info) is 8

bit_info中的a, b占用4個字節的前4位,到int:0; 時表現此時將填充余下一切沒有填充的位,即方才的4個字節的余下28位;int d:2; 將從第四個字節開端填充,又會占用4個字節,所以總年夜小為8.

再來看上面幾個小例子
例1:

struct A{ 
        char f1 : 3; 
        char f2 : 4; 
        char f3 : 5; 
    };

                    a      b          c
A的內存結構:111,1111 *,11111 * * *
位域類型為char,第1個字節僅能包容下f1和f2,所以f2被緊縮到第1個字節中,而f3只能從下一個字節開端。是以sizeof(A)的成果為2。
例2:

struct B{ 
        char f1 : 3; 
        short f2 : 4; 
        char f3 : 5; 
    };

因為相鄰位域類型分歧,在VC6中其sizeof為6,在Dev-C++中為2。
例3:

struct C{ 
        char f1 : 3; 
        char f2; 
        char f3 : 5; 
    };

非位域字段交叉在個中,不會發生緊縮,在VC6和Dev-C++中獲得的年夜小均為3。
斟酌一個成績,為何要設計內存對齊的處置方法呢?假如系統構造是纰謬齊的,成員將會一個挨一個存儲,明顯對齊更糟蹋了空間。那末為何要應用對齊呢?系統構造的對齊和纰謬齊,是在時光和空間上的一個衡量。對齊節儉了時光。假定一個別系構造的字長為w,那末它同時就假定了在這類系統構造上對寬度為w的數據的處置最頻仍也是最主要的。它的設計也是從優先進步對w位數據操作的效力來斟酌的。有興致的可以谷歌一下,人家便可以跟你說明的,一年夜堆的事理。
最初趁便提一點,在設計構造體的時刻,普通會尊照一個習氣,就是把占用空間小的類型排在後面,占用空間年夜的類型排在前面,如許可以絕對勤儉一些對齊空間。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved