C++ 结构体内存对齐

2024-05-16 14:52
文章标签 c++ 结构 对齐 体内

本文主要是介绍C++ 结构体内存对齐,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

定义了两个结构体

 typedef struct Cmd {uint8_t ua;uint8_t ub;uint8_t uc;uint32_t ue;
} Cmd_t;typedef struct Cmd_tag {uint8_t value;uint8_t data[1]; // 将 data 定义为指向 Cmd_t 结构体的指针
} tag_t;

在实际使用中,看见前人的代码是,new 一块内存放两个结构体。我对内存大小有些疑惑。代码如下

void test2()
{int size = 9;unsigned char* pdata = new unsigned char[size];memset(pdata, 0, size);// 解释 pdata 为 tag_t* 类型的指针tag_t* pCmd = (tag_t*)pdata;pCmd->value = 1;// 将 pdata + 1 解释为 Cmd_t* 类型的指针,并将其赋给 data 成员Cmd_t*  p= (Cmd_t*)(pdata + 1);p->ua = 10;p->ub = 10;p->uc = 10;p->ue = 10;std::cout << "value: " << static_cast<int>(pCmd->value) << std::endl;std::cout << "Address of pCmd->value: " << static_cast<void*>(&pCmd->value) << std::endl;std::cout << "data->a: " << static_cast<int>(p->ua) << std::endl;std::cout << "Address of p->a: " << static_cast<void*>(&p->ua) << std::endl;std::cout << "data->ub: " << static_cast<int>(p->ub) << std::endl;std::cout << "Address of p->ub: " << static_cast<void*>(&p->ub) << std::endl;std::cout << "data->uc: " << static_cast<int>(p->uc) << std::endl;std::cout << "Address of p->uc: " << static_cast<void*>(&p->uc) << std::endl;std::cout << "data->ue: " << p->ue << std::endl;std::cout << "Address of p->ue: " << static_cast<void*>(&p->ue) << std::endl;delete[] pdata;
}

输出如下
在这里插入图片描述
解释:

 std::cout << "Size of tag_t: " << sizeof(tag_t) << " bytes" << std::endl;std::cout << "Size of Cmd_t: " << sizeof(Cmd_t) << " bytes" << std::endl;
// Size of tag_t: 2 bytes//Size of Cmd_t: 8 bytes

结构体 tag_t需要2 bytes
结构体 Cmd_t 需要 8 bytes

一开始我以为,new一块内存存放她两需要 2+8 =10 bytes
但是由于 将 pdata + 1 解释为 Cmd_t* 类型的指针,并将其赋给 data 成员

Cmd_t*  p= (Cmd_t*)(pdata + 1);

相当于 Cmd_tag.data 和 Cmd_t.ua公用一个字节的内存

所以new的时候只需要 9 bytes

.还有一个坑:
最开始计算Cmd_t大小时 ,我以为是7bytes. 后来发现C++ 结构体在这里右4字节对齐
可以观察输出, p->ue的地址比 p->uc的地址增加了 2
所以如果代码里,size =8 程序会崩溃

这篇关于C++ 结构体内存对齐的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/995226

相关文章

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

PostgreSQL如何查询表结构和索引信息

《PostgreSQL如何查询表结构和索引信息》文章介绍了在PostgreSQL中查询表结构和索引信息的几种方法,包括使用`d`元命令、系统数据字典查询以及使用可视化工具DBeaver... 目录前言使用\d元命令查看表字段信息和索引信息通过系统数据字典查询表结构通过系统数据字典查询索引信息查询所有的表名可

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�