零基础入门之结构体字节对齐

一、字节对齐的规则:

1、一般设置的对齐方式为1,2,4字节对齐方式。结构的首地址必须是结构内最宽类型的整数倍地址;另外,结构体的每一个成员起始地址必须是自身类型大小的整数倍(需要特别注意的是windows下是这样的,但在linux的gcc编译器下最高为4字节对齐),否则在前一类型后补0;这里特别提到的是数组一定要注意,而且在一些编程的技巧中,我们可以使用数组强制字节达到对齐的目的。这在网络编程中是很常见的。

举例:比如CHAR型占用空间为1字节,则其起始位置必须可被1整除。INT为4字节,其起始位置必须被4带队,依次类推。(我们假定类或结构体的起始位置为0位置,其实编译器是在开辟空间时,会寻找起始位置可被结构内最宽类型整除的地址做为开始地址,因此我们可以假定其为0值,因为这0值可以被任意的类型整除。)

2、结构体的整体大小必须可被对齐值整除,默认4(结构中的类型大小都小于默认的4)。

3、结构体的整体大小必须可被本结构内的最宽类型整除。(其实和上一条是一样的,但这里独立出来,起注意作用。比如结构体里的有DOUBLE,那么结构的大小最后必须可被8整除)

注意:GCC不是这样,就是最高只能被4整除。此为32位系统,64为系统也会采用8整除的方式。否则(2、3条),编译器会在结构的最后添充一定的特定字符来补齐。

struct T
{
char ch;
double d ;
};

此结果强调为32系统在VC中是16个字节,GCC中为12个字节。64位依旧是16个字节

4、对于结构体内嵌套结构体的形势,规定是必须按照基本数据类型来定义,而不能以嵌套结构大小来做为上三种使用的基准。(总结)结构体可以处理成char类型。

二、举例:

struct A
{
    int a;
    char b;
    short c;
};  //8
struct B
{
    char b;
    int a;
    short c;
};  // 12
struct C
{
    double t;
    char b;
    int a;
    short c;
}; //24
struct D
{
    char b;
    double t;
    int a;
    short c; 

};//24

在VC中,SIZEOF这四个结构体,分别为:8、12、24、24;

我们先谈第一个,(说明一下,在考虑结构体大小时,我们基本可以忽略起始地址的问题,因为这个编

译器会自动为我们做好,见上面的说明),结构体内首先是一个INT的4字节,起始地址假定为0,整除4,其小于等于默认的4字节对齐且0为4(INT的占用空间)的整数倍,所以,其占四个字节;其后为起始地址为5,空间为1个字节的CHAR,小于4且5为1(CHAR占用空间)的整数倍,故占用1个字节,然后是一个起始地址为5占2个字节的SHORT,其小于4,但5不为2位数,故补齐一个字节,从第6个字节开始,占2字节空间。所以共占用4+1+1(补)+2=8;8/4=2;整除,故占用8字节空间。

再谈第2个,CHAR不用解释,占有一个字节空间,且可以被0地址整除。而INT则占4字节空间,所以其必须在CHAR后补齐3字节,到第四个字节,才是INT的真正地址。SHORT也不用说,所以共占有:1+3(补)+4+2=10个字节,但10不能整除4,所以要在结构体最后补齐2字节。故实际占有10+2=
12个字节。

谈第三个,C结构体只是在B结构体前加了一个DOUBLE,其它都一样,按说应该是20个字节啊,但注意我们上面规则的第3条。必须是最宽类型的整数倍,一定要分清,所以得补齐到24,D结构体类似,不再讲。

Linux系统32位与64位GCC编译器基本数据类型长度对照表


GCC
32位
sizeof(char)
= 1
sizeof(double)
= 8
sizeof(float)
= 4
sizeof(int)
= 4
sizeof(short)
= 2
sizeof(long)
= 4
sizeof(long
long) = 8
sizeof(long
double) = 12
sizeof(complex
long double) = 24
指针是4字节;

GCC
64位
sizeof(char)
= 1
sizeof(double)
= 8
sizeof(float)
= 4
sizeof(int)
= 4
sizeof(short)
= 2
sizeof(long)
= 8
sizeof(long
long) = 8
sizeof(long
double) = 16
sizeof(complex
long double) = 32

指针是8字节

实例参考:

GNU
C扩展的__attribute__ 机制被用来设置函数、变量、类型的属性,其用得较多的是处理字节对齐的问题。
__attribute__ 的语法为:
__attribute__ ((语法列表))参数aligned(number)
[number为最小对齐的字节数]是用得较多的一个。
另一个是参数packed
表示“使用最小对齐”方式,即对变量是字节对齐,对于域是位对齐。

#include
struct A{
 char a;          //1Byte
 int b;           //4B
 unsigned short c;//2B
 long d;          //4B
 unsigned long long e; //8B
 char f;               //1B
};

struct B{
 char a;
 int b;
 unsigned short c;
 long d;
 unsigned long long e;
 char f;
}__attribute__((aligned));

struct C{
 char a;
 int b;
 unsigned short c;
 long d;
 unsigned long long e;
 char f;
}__attribute__((aligned(1)));

struct D{
 char a;
 int b;
 unsigned short c;
 long d;
 unsigned long long e;
 char f;
}__attribute__((aligned(4)));

struct E{
 char a;
 int b;
 unsigned short c;
 long d;
 unsigned long long e;
 char f;
}__attribute__((aligned(8)));

struct F{
 char a;
 int b;
 unsigned short c;
 long d;
 unsigned long long e;
 char f;
}__attribute__((packed));

struct H{
 char a;
 double b;
};
int main(int argc, char **argv)
{
 struct A a;
 struct B b;
 struct C c;
 struct D d;
 struct E e;
 struct F f;

 printf("A = %d, B = %d, C = %d, D = %d, E = %d, F = %d, H = %d\n",
   sizeof(struct A), sizeof(struct B), sizeof(struct C), sizeof(struct D), sizeof(struct E),      sizeof(struct F),sizeof(struct H));
 return 0;
}
 

结果:

$ ./aligned32
A = 28, B = 32, C = 28, D = 28, E = 32, F = 20, H = 12
$ ./aligned64
A = 40, B = 48, C = 40, D = 40, E = 40, F = 24, H = 16 

分享一些C语言相关的资料

结构体普及与应用
http://www.makeru.com.cn/live/5413_1909.html?s=45051
C语言玩转链表
http://www.makeru.com.cn/live/1392_338.html?s=45051

必备Linux命令和C语言基础
http://www.makeru.com.cn/video/1862.html?s=45051

释放潜能:学习效率提升、编程能力提升
http://www.makeru.com.cn/live/3507_1276.html?s=45051

原文地址:https://www.cnblogs.com/923327iu/p/11848655.html

时间: 2024-11-08 16:31:21

零基础入门之结构体字节对齐的相关文章

结构体字节对齐

结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列, 而不是简单地顺序排列,这就是内存对齐. 内存对齐的原因: 1)某些平台只能在特定的地址处访问特定类型的数据: 2)提高存取数据的速度.比如有的平台每次都是从偶地址处读取数据,对于一个int型的

结构体字节对齐问题(转)

原文出处:http://wenku.baidu.com/view/019e26b765ce0508763213e2.html 初学C,对结构体的使用sizeof计算所占字节数不是很明白,看了此篇文章,终于豁然开朗,转载过来,方便以后温故. #include<stdio.h> struct a {   char no[10];   int p;   long int pp;   unsigned int ppp;   char x;   float y;   double h; }xy; voi

C++结构体字节对齐

本站文章均为Jensen抹茶喵原创,转载务必在明显处注明:转载自[博客园] 原文链接:http://www.cnblogs.com/JensenCat/p/4770171.html 直接上源码吧!~ 这里是头文件结构的定义: 一个非字节对齐结构体_tagTest2 一个字节对齐_tagTest3 (使用#pragma pack(push,1)来使字节以1个来对齐 , 使用#pragma pack(pop)来还原默认) 1 #pragma once 2 3 4 struct _tagTest1 5

结构体 字节对齐

转自:http://www.cnblogs.com/longlybits/articles/2385343.html   (有改动) 内存对齐 在用sizeof运算符求某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列,而不是简单地顺序排列,这就是内存对齐. 内存对齐的原因: 1)某些平台

关于结构体字节对齐的笔记

1,空结构体的字节大小为:1: 2,含有static成员的结构体:sizeof 只算存栈中分配的空间大小,static成员存储在全局数据区内,故 static 成员变量不计算在内. 3,在默认对齐方式中,每种类型的存储开始地址是 能被该类型大小整除的地址.故:每次计算都假设结构体开始地址是 0: 4,遇到成员是结构体变量的:将此结构体变量当做一个数据类型,但是: 注意: 千万不能把此结构体的 sizeof 当做该变量的类型大小 也不能直接将此结构体拆解开 解法: 此结构体成员变量的类型大小 理解

C#.NET结构体字节对齐[转载]

[StructLayout(LayoutKind.Sequential,   CharSet=CharSet.Ansi)]     internal   struct   DllInvoices     {     [MarshalAs(UnmanagedType.ByValArray,   SizeConst=8)]     public   byte[]   serial;     public   byte   Type;     public   uint   Sum;     }   

结构体边界对齐

结构体边界对其是一个老生常谈的话题了,网上的解释非常多,但大多偏重于讲步骤,对于每一步的原因都有点不清楚的地方,下面结合网上的讲解和自己的理解谈谈结构体对齐,不一定正确. 1.什么是结构体对齐. struct A{ char  a: char b: int c: char  d: } 对于上面的这个结构体,假设机器字长32位(4字节),那么该结构体变量占用的空间并非1+1+4+1=7,而是1+3+4+1+3=12.编译器自动将c的起始位置调整到第4个字节处,并在结构体最后加了3个字节,这种编译器

(转)零基础入门深度学习(6) - 长短时记忆网络(LSTM)

无论即将到来的是大数据时代还是人工智能时代,亦或是传统行业使用人工智能在云上处理大数据的时代,作为一个有理想有追求的程序员,不懂深度学习(Deep Learning)这个超热的技术,会不会感觉马上就out了?现在救命稻草来了,<零基础入门深度学习>系列文章旨在讲帮助爱编程的你从零基础达到入门级水平.零基础意味着你不需要太多的数学知识,只要会写程序就行了,没错,这是专门为程序员写的文章.虽然文中会有很多公式你也许看不懂,但同时也会有更多的代码,程序员的你一定能看懂的(我周围是一群狂热的Clean

从零基础入门JavaScript(1)

从零基础入门JavaScript(1) 1.1  Javascript的简史 1995年的时候   由网景公司开发的,当时的名字叫livescript    为了推广自己的livescript,搭了java顺风车,改名为javascript 与此同时,     微软因此在自身的浏览器里,也推出了自己的脚本语言 jscript 1997年时候,  由ECMA(欧洲计算机制造商协会)出面,推出了一套javascript的规范,Ecmascript ,规范提出js由三部分组成 JS的组成: ECMAS