C语言深入回顾讲解结构体对齐

目录
  • 结构体对齐问题
  • 结构体嵌套结构体
  • 强制内存对齐
  • 拓展求结构体成员的偏移量

结构体对齐问题

1、知识点的引入:

struct data1
{
    char a;//1B
    int b;//4B
};
void test01()
{
    printf("%d\n",sizeof(struct data1));//8B 为啥?
}

2、对齐规则(默认对齐)

第一步:确定分配单位(每行开辟多少字节)

结构体中最大的基本类型的长度 为分配单位。

第二步:确定成员的偏移位置。

偏移位置:成员自身类型的整数倍(0~n倍)

第三步:收尾工作:

结构体的总大小必须是分配单位的整数倍

struct data
{
	char c;//1B
	int i;//4B
};
void test05()
{
	struct data d;
	//结构体的大小 >= 成员大小之和
	printf("%d\n",sizeof(struct data));//8
	printf("&d.c = %u\n",&d.c );
	printf("&d.i = %u\n",&d.i );
}

运行结果:

案例:

typedef struct
{
	int a;
	char b;
	short c;
	char d;
}DATA;
void test06()
{
	DATA d;
	printf("%d\n", sizeof(DATA));
	printf("%u\n", &d.a);
	printf("%u\n", &d.b);
	printf("%u\n", &d.c);
	printf("%u\n", &d.d);
}

案例1:

struct data1
{
    char a;//1B
    int b;//4B
};

案例2:

struct data2
{
    char a;
    short b;
    char c;
    int d;
};

案例3:

struct data2
{
    char a;
    short b;
    short c;
    char d;
};

案例4:

struct data2
{
    char a[7];
    short b;
    int c;
};

结构体嵌套结构体

第一步:确定分配单位(每行开辟多少字节)

所有结构体中最大的基本类型的长度 为分配单位。

第二步:确定成员的偏移位置。

普通成员偏移位置:成员自身类型的整数倍(0~n倍)

结构体成员的偏移量:该结构体的最大基本类型的整数倍

第三步:收尾工作:

结构体成员:是该结构体的最大基本类型整数倍。

结构体的总大小必须是分配单位的整数倍

案例:

typedef struct
{
	short d;
	char e;
}DATA2;
typedef struct
{
	short a;
	int b;
	DATA2 c;
	char f;
}DATA;
void test08()
{
	DATA data;
	printf("%d\n",sizeof(DATA));
	printf("a:%u\n", &data.a);
	printf("b:%u\n", &data.b);
	printf("c中d:%u\n",&data.c.d);
	printf("c中e:%u\n",&data.c.e);
	printf("f:%u\n",&data.f);
}

案例:

typedef struct
{
	char a;
	int b;
	short c;
}DATA;
void test10()
{
	DATA data={'a',100, 20};
	char *p = &data;
	printf("c = %hd\n", data.c);
	//需求 借助p访问20
	printf("c = %hd\n", *(short *)(p+8));
}

运行结果:

案例:

struct A
{
    char b;
    short c;
};
struct B
{
    int a;
    struct A ob;//结构体成员的偏移量
    int d;
};

案例1:

struct A
{
    short b;
    char c;
};
struct B
{
    int f;
    char a;
    struct A ob;//结构体成员的偏移量
    char d;
};

强制内存对齐

#pragma pack (value)时的指定对齐值value

第一步:确定分配单位(每行开辟多少字节)

min(value,最大的基本类型的长度) 为分配单位。

第二步:确定成员的偏移位置。

偏移位置:成员自身类型的整数倍(0~n倍)

第三步:收尾工作:

结构体的总大小必须是分配单位的整数倍

#include <stdio.h>
#include<stdio.h>
#pragma pack (4)
struct stu
{
    char a;
    short b;
    short c;
};
void test01()
{
    printf("%d\n",sizeof(struct stu));//6
}

注意事项:

拓展求结构体成员的偏移量

struct stu1
{
    char a;
    int b;
    char c;
    int d;
};

#include <stdio.h>
#include<stdio.h>
struct stu1
{
    char a;
    int b;
    char c;
    int d;
};
#define  OFF_SET(TYPE, member) (int)&(((TYPE *)0)->member)
void test01()
{
    struct stu1 data;
    printf("偏移量:%d\n",   OFF_SET(struct stu1, b) );//8
}

到此这篇关于C语言深入回顾讲解结构体对齐的文章就介绍到这了,更多相关C语言结构体对齐内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言结构体中内存对齐的问题理解

    目录 前言 思考 结构体在内存中开辟空间时内存对齐的规则 为什么存在内存对齐 1.平台的原因 2.性能的原因 前言 学C的同学应该知道~ 想精通C语言就不得不面对—指针与内存 续上次指针的进阶,这一章我来聊一聊C语言内存对齐的问题 学习结构体的你有没有注意过结构体向系统申请的内存为多少呢的 思考 #include<stdio.h> typedef struct s1 { char a; char b; int c; }s1; typedef struct s2 { char a; int c;

  • C语言详解热门考点结构体内存对齐

    目录 一.为什么存在内存对齐 二.如何计算?(考点) 三.手撕代码 一.为什么存在内存对齐 大部分的参考资料都是如是说的: 1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的:某些硬件平台只能再某些地址处取某些特定类型的数据,否则抛出硬件异常. 2.性能原因:数据结构(尤其是栈)应该尽可能地再自然边界上对齐.原因在于,为了访问未对其的内存,处理器需要作两次内存访问:而对齐的内存访问仅需要一次访问. 总体来说:结构体的内存对齐是拿空间来换取时间的做法 二.如何计算?(考点)

  • C语言结构体内存对齐详解

    目录 实例一: 分析:存储结构图如下 实例二: 分析:存储结构如下 实例三: 分析:存储结构如下 实例四: 分析:存储结构图如下 总结 1.结构体内存对齐是指当我们创建一个结构体变量时,会向内存申请所需的空间,用来存储结构体成员的内容.我们可以将其理解为结构体成员会按照特定的规则来存储数据内容. 2.结构体的对齐规则 (1)第一个成员在相比于结构体变量存储起始位置偏移量为0的地址处. (2)从第二个成员开始,在其自身对齐数的整数倍开始存储(对齐数=编译器默认对齐数和成员字节大小的最小值,VS编译

  • c语言结构体字节对齐的实现方法

    目录 1.什么是字节对齐 2.为什么要有字节对齐 3.手动设置对齐 4.结构体比较方法 1.什么是字节对齐 在c语言的结构体里面一般会按照某种规则去进行字节对齐. 我们先看一段代码: struct st1 { char name; double age; char sex; }; //32位下 sizeof(struct st1) = 16 //64位下 sizeof(struct st1) = 24 struct st2 { char a; char b; char c; }; //32位和6

  • C语言中结构体与内存对齐实例解析

    1.结构体类型 C语言中的2种类型:原生类型和自定义类型,结构体类型是一种自定义类型. 2.结构体使用时先定义结构体类型再用类型定义变量 -> 结构体定义时需要先定义结构体类型,然后再用类型来定义变量. -> 也可以在定义结构体类型的同时定义结构体变量. // 定义类型 struct people { char name[20]; int age; }; // 定义类型的同时定义变量. struct student { char name[20]; int age; }s1; // 将类型st

  • C语言热门考点结构体与内存对齐详解

    目录 一.引例 1.结构体的第一个成员永远放在结构体起始位置偏移量为0的位置 2.从第二个成员开始,总是放在偏移量为一个对齐数的整数处,对齐数=编译器默认的对齐数和变量自身大小的较小值 3.结构体的总大小必须是各个成员的对齐数中最大的那个对齐数的整数倍 二.小试牛刀 三.嵌套结构体的特殊情况 四.关于为什么存在内存对齐 1.平台原因(移植原因): 2.性能原因: 总结 一.引例 到底什么是结构体内存对齐,我们用一段代码来介绍一下 struct S1 { char c1;//1字节 int a;/

  • C语言 详细分析结构体的内存对齐

    目录 一.结构体 二.结构体内存对齐 1.非嵌套结构体的大小 2.含嵌套结构体的大小 三.为什么要内存对齐 1.平台原因(移植原因) 2.性能原因 一.结构体 结构体 (struct)是一种数据结构,可以包含很多数据类型,可以实现比较复杂的数据结构. 常见的int,char类型变量,我们可以一眼看出占多少字节,但对于结构体,可就有点难度了. 让我们来猜猜以下程序的输出 struct S1 { char c1; int i; char c2; }; struct S2 { char c1; cha

  • C语言中结构体的内存对齐规则讲解

    目录 1.结构体的内存对齐规则 2.例子 3.为什么存在内存对齐 4.如何修改默认对齐数 1.结构体的内存对齐规则 1.第一个成员在与结构体变量偏移量为0的地址处. 2.其他成员变量都放在对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处. 对齐数=编译器默认的一个对齐数与该成员大小的较小值.(VS中默认的对齐数是8) 3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数 )的整数倍. 4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最

  • C语言详解结构体的内存对齐与大小计算

    目录 结构体的内存对齐 1.计算结构体的大小 2.结构体的对齐规则 3.为什么存在内存对齐? 4.总结 结构体的内存对齐 1.计算结构体的大小 struct S1 { char c1; // 1 byte,默认对齐数为8,所以c1的对齐数是1,第一个成员变量放在与结构体变量偏移量为0的地址处 int i; // 4 byte,默认对齐数为8,所以i的对齐数是4,所以i要放到偏移量为 4的整数倍 的地址处 char c2; // 1 byte,默认对齐数为8,所以c2的对齐数是1,所以c2要放到偏

  • C语言深入回顾讲解结构体对齐

    目录 结构体对齐问题 结构体嵌套结构体 强制内存对齐 拓展求结构体成员的偏移量 结构体对齐问题 1.知识点的引入: struct data1 { char a;//1B int b;//4B }; void test01() { printf("%d\n",sizeof(struct data1));//8B 为啥? } 2.对齐规则(默认对齐) 第一步:确定分配单位(每行开辟多少字节) 结构体中最大的基本类型的长度 为分配单位. 第二步:确定成员的偏移位置. 偏移位置:成员自身类型的

  • C语言简明清晰讲解结构体

    目录 本质 简单使用 一些写法 我套我自己 内存对齐 举例-int char char 举例-char int char 举例-char char int 由结构体指针访问成员 本质 一些值的集合. 简单使用 #include <stdio.h> struct User { char uName[20]; char uPass[20]; }; int main() { struct User u1 = { "abc","123" }; printf(&q

  • C语言超详细讲解结构体与联合体的使用

    目录 结构体 offsetof-宏 位段 枚举 联合体(共用体) 结构体 结构体内存对齐问题: 当我们在计算结构体的大小时,我们便需要清楚的知道结构体内存对齐是什么. 存在内存对齐的原因可细分为两个: 平台原因: 不是所有的硬件平台都能方位任意地址上的任意数据:某些硬件平台只能在某些地址处取某些特定类型的数据,否则会抛出硬件异常. 性能原因: 首先内存对齐可以提高程序的性能,当访问未对其的内存空间时,有时候处理器需要进行两次访问,而当访问对齐的内存时,只需要一次就够了.这同时也被叫做 用空间换取

  • 实例讲解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 - (

  • C语言示例讲解结构体的声明与初始化方法

    目录 一.结构体声明的结构 1.直接声明 2.使用typedef声明一个新的类型 3.不完全声明 二.结构体初始化 1.声明(同时定义)时直接赋值 2.定义时直接赋值 3.定义后赋值 4.指定初始化 一.结构体声明的结构 1.直接声明 struct tag { member-list: member-list: member-list: ... } variable-list; tag 是结构体类型的标签. member-list 结构体的元素定义,比如 int i; 或者 float f,或者

  • C语言自定义数据类型的结构体、枚举和联合详解

    结构体基础知识 首先结构体的出现是因为我们使用C语言的基本类型无法满足我们的需求,比如我们要描述一本书,就需要书名,作者,价格,出版社等等一系列的属性,无疑C语言的基本数据类型无法解决,所以就出现了最重要的自定义数据类型,结构体. 首先我们创建一个书的结构体类型来认识一下 struct Book { char name[20]; char author[20]; int price; }; 首先是struct是结构体关键字,用来告诉编译器你这里声明的是一个结构体类型而不是其他的东西,然后是Boo

  • C语言位段(位域)机制结构体的特殊实现及解析

    目录 概念 内存分配 位段跨平台问题 作用 Tip 应用场景 概念 什么是位段? 位段又称为位域,C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员就叫做称为位段( bit field) .利用位段能够用较少的位数存储数据达到节省空间的目的. 位段是结构体特有的,所以声明是和结构是类似的,但有两个不同: 1. 位段成员必须是 int ,unsigned int,signed int 2. 位段成员名后边结构包括一个冒号和整型数字 举个栗子: struct haha

  • 结构体对齐的规则详解及C++代码验证

    目录 基本概念 结构体对齐的规则 程序验证 基本概念 CPU一次能读取多少个字节的数据主要是看数据总线是多少位的,16位CPU一次能读取2个字节,32位CPU一次能读取4个字节,64位CPU一次能读取8个字节.并且不能跨内存区间访问,这句话的意思可以理解为,如果CPU是32位的话,那么可以将整个内存区间每4个字节分为一块(BLOCK),每次读取一个BLOCK的数据. 那么对于下面这个结构体: struct st { char c; int i; }; 如果不进行对齐操作,char 的地址范围0x

  • C语言入门篇--初识结构体

    目录 1.为什么要有结构体 2.结构体的定义 2.1结构体类型的定义 2.2定义结构体普通变量及访问 2.3定义结构体指针变量及访问 1.为什么要有结构体 (1)之前int.char等类型描述的结构体非常单一,只可描述一种类型. (2)数组也是描述同一类型的集合,只可描述一种类型. (3)而结构体使得C语言可以描述复杂类型,比如学生类型( 包含学生的名字.年龄.性别.电话号等信息). 结构体和数组的区别: 结构体:用来描述相同/不同数据元素类型的集合. 数组:用来描述具有相同数据元素类型的集合.

  • Go语言基础语法之结构体及方法详解

    结构体类型可以用来保存不同类型的数据,也可以通过方法的形式来声明它的行为.本文将介绍go语言中的结构体和方法,以及"继承"的实现方法. 结构体类型 结构体类型(struct)在go语言中具有重要地位,它是实现go语言面向对象编程的重要工具.go语言中没有类的概念,可以使用结构体实现类似的功能,传统的OOP(Object-Oriented Programming)思想中的继承在go中可以通过嵌入字段的方式实现. 结构体的声明与定义: // 使用关键字 type 和 struct 定义名字

随机推荐