首页 > 系统相关 >C语言:结构体在内存中存储(内存对齐)

C语言:结构体在内存中存储(内存对齐)

时间:2024-09-17 23:49:18浏览次数:11  
标签:int person1 C语言 Person 体在 内存 对齐 结构

一、结构体是什么

1.结构体的声明

2.结构体的初始化

二、结构体的内存对齐

1.对齐规则

 2.为什么存在内存对齐

总结


前言

结构体是重要的知识点,其中,结构体的内存对齐是较重要的部分(本人使用的编译器是VisualStudio2022,下面介绍的对齐数也是以VS默认的8为标准),对后面学习数据结构有很大的帮助,因为结构体是自定义数据类型,可以在一个集合中处理不同的数据,所以在做题的时候用结构体也会带来极大的灵活性。以下是自己自学这部分知识总结的结构体方面的见解和体会,希望能给各位朋友们带来一点帮助,也希望各位大佬们对本篇文章多多提出自己的意见。

一、结构体是什么

在C语言中,结构体(structure)是一种用户自定义的数据类型,它允许你将不同类型的数据组合在一起,形成一个更复杂的数据类型。结构体在编程中非常有用,特别是当你需要处理由多个相关部分组成的数据时。

1.结构体的声明

结构体的声明使用struct关键字,后面跟着结构体的名称和成员列表。成员列表用花括号{}括起来,每个成员都是某种数据类型的一个变量,成员之间用分号;分隔下面是一个简单的结构体声明的例子:

struct Person {  
    char name[10];  
    int age;  
    float height;  
};

在这个例子中,Person是一个结构体的名称,它有三个成员name(一个字符数组,用于存储名字)age(一个整数,表示年龄)height(一个浮点数,表示身高)。 其实,结构体的声明就是告诉计算机,我们构建了一个自定义数据类型,叫Person,接着我们就可以和基本数据类型(int,float,char等)一样的使用创建变量了。

2.结构体的初始化

一旦声明了结构体,你就可以创建该类型的变量,并访问或修改其成员。例如:

#include <stdio.h>  
  
// 声明结构体  
struct Person {  
    char name[10];  
    int age;  
    float height;  
};  
  
int main() {  
    // 创建一个结构体变量  
    struct Person person1;  
  
    // 初始化结构体成员  
    strcpy(person1.name, "Alice");  
    person1.age = 30;  
    person1.height = 5.5;  
  
    // 访问结构体成员  
    printf("Name: %s\n", person1.name);  
    printf("Age: %d\n", person1.age);  
    printf("Height: %.1f\n", person1.height);  
  
    return 0;  
}

 

首先,我们声明了一个Person类型,接着 我们用Person创建了一个变量person1,然后我们初始化person1中的三个成员,最后调用并打印它们。

二、结构体的内存对齐

1.对齐规则

1)VS中的默认的值为8

2)Linux中的 gcc 没有默认对齐数,对齐数就是成员自身的大小 

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>  
#include<string.h>
// 声明结构体  
struct Person {
    char name[10];
    int age;
    float height;
};

int main() {
    // 创建一个结构体变量  
    struct Person person1;

    int ans = sizeof(person1);
    printf("内存大小为:%d", ans);

    return 0;
}

 

对上述的代码,画出该结构体的内存结构图,如下图:

 

 2.为什么存在内存对齐

大部分的参考资料 是这样说的:

1)平台原因(移植原因):

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

2)性能原因:

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。假设一个处理器总是从内存中取8个字节,则地址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对齐成8的倍数,那么就可以用一个内存操作来读或者写值了。否则,我们可能需要执行两次内存访问,因为对象可能被分成放在两个8字节内存块中。

总体来说:结构体的内存对齐是拿空间来换取时间的做法。所以,在设计结构体的时候,我们既要满足对齐,又要节省空间,就要让占用空间小的成员尽量集中在一起

3.自定义设置编译器的默认对齐数

用pragma pack()来修改默认对齐数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>  
#include<string.h>
#pragma pack(1)
// 声明结构体  
struct Person {
    char name[10];
    int age;
    float height;
};

int main() {
    // 创建一个结构体变量  
    struct Person person1;

    int ans = sizeof(person1);
    printf("内存大小为:%d", ans);

    return 0;
}

 

 这里,我们修改默认对齐数为1,成员name[10]的最终对齐数为:1,成员age的最终对齐数为:1,成员height的最终对齐数为:1,所以此时,该结构体的最大对齐数为:1,此时总空间大小是:10+4+4=18

总结

在内存中,结构体这种自定义类型的存储方式还是很值得学习的,希望各位大佬多多提出自己的见解,以便我可以及时修改更新错的知识点,在此谢谢各位!

标签:int,person1,C语言,Person,体在,内存,对齐,结构
From: https://blog.csdn.net/2301_80966914/article/details/142319539

相关文章

  • C语言:整数和浮点数在内存中的存储--(超好理解)
    目录一、整数在内存中的存储(有符号整数)1.设置反码和补码的的目的二、浮点数在内存中的存储1.浮点数取的过程2.例题解析总结目前学习到C语言的各种数据类型在内存中的存储的方式和过程,自己初学的时候下了很多时间去学习理解,为了帮助和自己一样的在第一次初学C语言存储......
  • 操作系统知识强化内存映射文件(25王道)
    内存映射文件本文根据25王道操作系统内存映射文件这一章所作跟课笔记什么是内存映射文件首先来看看什么是内存映射文件。简单来说,这是操作系统向上层的程序员提供的一个系统调用功能。通过这个功能,程序员可以很方便的去访问文件数据,另外这个功能也可以很方便的让多个进程......
  • 【时时三省】(C语言基础)指针进阶 例题8
    山不在高,有仙则名。水不在深,有龙则灵。              ----CSDN时时三省第一个打印2a+6不管它是多大前面是=s 都得变成两个字节所以打印2第二个打印5sizeof里面的表达式是不参与运算的所以打印5上面所有例题总结:数组名的意义1.sizeof(......
  • 进程的内存分配
    在操作系统中,进程的内存分配是指操作系统为每个进程管理和分配所需的内存资源。内存管理是操作系统的核心功能之一,它涉及到为进程提供虚拟内存、物理内存分配、页表管理、以及地址转换等操作。操作系统通过虚拟内存机制,使每个进程都可以认为自己拥有独立的、连续的内存空间。1.......
  • 深入剖析:C++类对象的内存布局与优化
    深入剖析:C++类对象的内存布局与优化引言在C++编程中,理解类对象的内存布局对于优化内存使用和提高程序性能至关重要。本文将详细介绍C++类对象的内存布局,包括数据成员、虚函数表指针以及静态变量和静态方法在内存中的位置。通过这些知识,我们可以更好地设计和优化我们的类结......
  • 前端JavaScript面试重难点: 闭包+内存泄漏+垃圾回收机制
    前置知识!!!闭包是Javascript语言的一个重难点,也是它的特色,很多高级应用都要依靠闭包来实现。在各种专业文献上学习"闭包"的时候,就一个感觉–“抽象”!特别是学习内存泄漏的时候,没想明白为什么使用闭包的时候不及时清除函数中的元素会导致内存泄漏,直到我的......
  • JVM 内存
    目录堆栈默认垃圾回收策略垃圾回收参数G1垃圾回收查看内存的命令堆栈堆:存储对象和数组,堆大小动态分配(-Xms、-Xmx),线程共享,垃圾回收栈:存储局部变量、方法参数、方法栈,相对较小(-Xss),方法完成时释放,线程私有堆栈大小配置-Xmx:设置JVM最大可用内存,默认系统内存的1/4,最大......
  • 支持外部内存功能的STL容器使用方法分享
    一、分享简介    C++的STL支持了多种容器供开发者操作,然而这些容器使用的是系统内存,使用者无法直接管理。边缘端的嵌入式设备通常会要求对使用的内存进行管理,因此封装出支持外部内存功能的STL容器就显得十分必要。本案例针对被封装容器的使用方法进行了经验分享,具体涉及3......
  • C++内存管理详解:各类变量的存储区域
      在C++中,变量的存储位置取决于它们的类型和生命周期。那么不同的各个变量究竟存储在哪个区域呢?1.不同类型的变量我们首先从变量类型的不同来说明:1.全局变量和静态变量 -存储区:全局/静态区(静态区)-说明:全局变量(包括文件级和函数级的)和使用`static`关键字声明的变......
  • C语言--指针
    1.地址与指针想要弄明白什么是指针,就必须了解数据在内存中是如何储存的,又是怎么被读取的。系统会按字节对每个内存单元进行编号,这些内存单元就好比是许多带有编号的小房间,想要使用内存,就需要知道房间编号。每一个房间都有一个地址,我们通过访问地址就能找到相应的房间。那我......