C语言结构体内存对齐

简介: 结构体类型的声明结构体自引用结构体变量的定义和初始化结构体内存对齐结构体传参

结构体

结构体的声明

结构体是一些值集合的,里面可以包括char,int,double等等的各种类型构成的一个新的类型,也就是说相当于自己基于C语言本身给出的类型自己把它组成一个集合。

它的声明格式如下:


struct 类型名{
  元素1;
  元素2;
  .....
};
``
例如描述一个学生
```cpp
struct  stu
{
  char name[20];//名字
  int age;//年龄
  char ID[20];//学号
};

结构体的自引用

我们知道结构体里面可以包括char,int ,double等等类型,那么通过上面我们讲的结构体它也是一种类型。只不过是我们自己定义的一种类型,那么我们可以在结构体里面定义一个结构体吗?


struct  stu
{
  char name[20];//名字
  int age;//年龄
  char ID[20];//学号
  struct stu next;
};

这里我们可以知道直接定义是不行的。

那么正确的自引用方式是下面这个

struct  stu
{
  char name[20];//名字
  int age;//年龄
  char ID[20];//学号
  struct stu *next;
};

这里在C语言后期链表期间给大家详细讲解


结构体变量的定义和初始化

struct  stu
{
  char name[20];//名字
  int age;//年龄
  char ID[20];//学号
}s1,s2;     //直接在结构体类型声明后直接定义
struct stu s1, s2;    //定义结构体
  struct stu s3 = { "张三",18,2022001 };//定义后直接初始化
  struct nau
  {
    int num;//号数
    char name[20];//名字
  } a1={18,"李四"};//直接在结构体类型声明后直接定义并初始化
  struct cmp
  {
    int i;
    struct nau;//结构体嵌套初始化
  }p1 = { 1,{18,"丽子"} };

结构体内存对齐

基本了解结构体的内容之后,我们就要计算结构体的大小了。

这也是一个特别热门的考点:

那么我们直接上几道练习


#include<stdio.h>
struct s
{
  char i;
  char j;
  int a;
}s1;
struct c
{
  char b;
  int b1;
  char b2;
}s2;
int main()
{
  printf("%d\n", sizeof(s1));//大小是多少呢? 
  printf("%d\n", sizeof(s2));//大小是多少呢?
  return 0;
}

如何计算?

首先得掌握结构体的对齐规则:

第一个成员在与结构体变量偏移量为0的地址处。

其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

VS中默认的值为8

结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就 是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。


为什么存在内存对齐?

平台原因(移植原因):

不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

性能原因:

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

简单来说就是用空间换取时间

967d9274076447fba4d24c16027141bf.png

那在设计结构体的时候,我们既要满足对齐,又要节省空间,我们要 让占用空间小的成员尽量集中在一起

struct S3
{
 double d;  //练习1
 char c;
 int i;
};
printf("%d\n", sizeof(struct S3));
//练习2-结构体嵌套问题
struct S4
{
 char c1;
 struct S3 s3;
 double d;
};
printf("%d\n", sizeof(struct S4));

上面s3的大小是16

s4的大小是32


结构体传参

详细请见结构体详解

对于结构体详解,后期会出改良优化过后的版本


相关文章
|
12天前
|
存储 编译器 程序员
C语言程序的基本结构
C语言程序的基本结构包括:1)预处理指令,如 `#include` 和 `#define`;2)主函数 `main()`,程序从这里开始执行;3)函数声明与定义,执行特定任务的代码块;4)变量声明与初始化,用于存储数据;5)语句和表达式,构成程序基本执行单位;6)注释,解释代码功能。示例代码展示了这些组成部分的应用。
27 10
|
10天前
|
C语言
C语言程序设计核心详解 第四章&&第五章 选择结构程序设计&&循环结构程序设计
本章节介绍了C语言中的选择结构,包括关系表达式、逻辑表达式及其运算符的优先级,并通过示例详细解释了 `if` 语句的不同形式和 `switch` 语句的使用方法。此外,还概述了循环结构,包括 `while`、`do-while` 和 `for` 循环,并解释了 `break` 和 `continue` 控制语句的功能。最后,提供了两道例题以加深理解。
|
10天前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
10天前
|
C语言
C语言程序设计核心详解 第三章:顺序结构,printf(),scanf()详解
本章介绍顺序结构的基本框架及C语言的标准输入输出。程序从`main()`开始依次执行,框架包括输入、计算和输出三部分。重点讲解了`printf()`与`scanf()`函数:`printf()`用于格式化输出,支持多种占位符;`scanf()`用于格式化输入,需注意普通字符与占位符的区别。此外还介绍了`putchar()`和`getchar()`函数,分别用于输出和接收单个字符。
|
10天前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
10天前
|
存储 C语言
C语言程序设计核心详解 第九章 结构体与链表概要详解
本文档详细介绍了C语言中的结构体与链表。首先,讲解了结构体的定义、初始化及使用方法,并演示了如何通过不同方式定义结构体变量。接着,介绍了指向结构体的指针及其应用,包括结构体变量和结构体数组的指针操作。随后,概述了链表的概念与定义,解释了链表的基本操作如动态分配、插入和删除。最后,简述了共用体类型及其变量定义与引用方法。通过本文档,读者可以全面了解结构体与链表的基础知识及实际应用技巧。
|
16天前
|
C语言
c语言中的结构体
本文档详细介绍了C语言中结构体的使用方法,包括结构体的基本定义、变量声明与赋值、数组与指针的应用,以及结构体嵌套、与`typedef`结合使用等内容。通过示例代码展示了如何操作结构体成员,并解释了内存对齐的概念。
|
22天前
|
C语言
C语言结构体赋值的四种方式
本文总结了C语言结构体的四种赋值方式,并通过示例代码和编译运行结果展示了每种方式的特点和效果。
34 6
|
1月前
|
编译器 程序员 Linux
【C语言篇】结构体和位段详细介绍
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。
|
1月前
|
存储 C语言
C语言------结构体和共用体
这篇文章是关于C语言中结构体和共用体的实训,通过示例代码演示了结构体的定义、赋值、使用,以及如何使用结构体变量进行数据的组织和操作,包括输入、排序、求平均分和查找学生信息等功能。
C语言------结构体和共用体