C语言字节对齐关键字__attribute__((aligned(n)))的使用

news2024/11/16 15:58:39

0 前言

在进行嵌入式开发的过程中,我们经常会见到对齐操作。这些对齐操作有些是为了便于实现指针操作,有些是为了加速对内存的访问。因此,学习如何使用对齐关键字是对于嵌入式开发是很有必要的。

1 对齐规则

1.0 什么叫做对齐

众所周知,内存的最小单位是字节。理论上,CPU可以访问内存上任意地址的数据,但实际上数据在内存中的分布并不是随意的,它们往往会遵循一定的对齐规则,使CPU访问这些数据的速度提升。
对齐实际上就是将变量存储的首地址按照1、2、4、8字节对齐,如果按照2字节对齐则变量在内存中的首地址必须是2的倍数,其它字节对齐方式也是如此。

1.1 默认的对齐方式

根据使用处理器、编译器的不同,变量在内存中的地址对齐方式不同。例如常见的STM32默认4字节对齐,本文使用的x64+vscode环境默认8字节对齐。

1.2 关键字attribute((aligned(n)))介绍

__attribute__((aligned(n)))
__attribute__((packed))

(1)attribute((aligned(n))):它的作用是对结构体整体进行n(n必须是2的幂)字节对齐,而不是为结构体成员进行对齐(使用结构体成员最大占用字节和指定字节对齐大小中最大的那个作为对齐标准)。它可以针对某个结构体进行对齐,也可以写在外部,对其后面的所有变量进行对齐操作
(2)attribute((packed)):按照1字节对齐(取消对齐)

2 实例测试

2.1 结构体成员默认的对齐方式

测试说明:
这里使用的是64位电脑,经过vscode后默认的对齐方式为按8字节对齐。
示例程序:

#include "stdio.h"

typedef struct
{
    unsigned char a;
    unsigned short int b;
    unsigned int c;
    double d;
} test_t;
test_t test;
int main(void)
{
    printf("a addr : 0x%x\r\n", &test.a);
    printf("b addr : 0x%x\r\n", &test.b);
    printf("c addr : 0x%x\r\n", &test.c);
    printf("d addr : 0x%x\r\n", &test.d);
    return 0;
}

我们这里定义了1个名为test_t的结构体,成员a、b、c、d的大小分别为1、2、4、8字节。在不做任何对齐操作下,打印a、b、c、d在内存上的地址:
在这里插入图片描述

可以看到,成员在结构体的分布对齐方式分别是1、2、4、8字节,同时结构体首地址也就是成员a的地址是按照8字节对齐的。它们在内存中的分布可以用如下示意图表示:
在这里插入图片描述

2.2 设置结构体成员按照1字节对齐

测试说明:
这里使用的是64位电脑,经过vscode后默认的对齐方式为按8字节对齐。
示例程序:

typedef struct __attribute__((packed))
{
    unsigned char a;
    unsigned short int b;
    unsigned int c;
    double d;
} test_t;
test_t test;

int main(void)
{
    printf("a addr : 0x%x\r\n", &test.a);
    printf("b addr : 0x%x\r\n", &test.b);
    printf("c addr : 0x%x\r\n", &test.c);
    printf("d addr : 0x%x\r\n", &test.d);
    return 0;
}

我们这里定义了1个名为test_t的结构体,成员a、b、c、d的大小分别为1、2、4、8字节。在按照1字节对齐之后,打印a、b、c、d在内存上的地址:
在这里插入图片描述
可以看到,成员在结构体的分布对齐方式是1字节,同时结构体首地址也就是成员a的地址是按照1字节对齐的。可以用如下的示意图表示使用__attribute__((packed))前后结构体成员在内存中的分布:
在这里插入图片描述

2.3 设置结构体变量32字节对齐

示例程序:

#include "stdio.h"
__attribute__((aligned(32)))
typedef struct
{
    unsigned char a;
    unsigned short int b;
    unsigned int c;
    double d;
} test_t;
test_t test;

int main(void)
{
    printf("a addr : 0x%x\r\n", &test.a);
    printf("b addr : 0x%x\r\n", &test.b);
    printf("c addr : 0x%x\r\n", &test.c);
    printf("d addr : 0x%x\r\n", &test.d);
    return 0;
}

我们这里定义了1个名为test_t的结构体,成员a、b、c、d的大小分别为1、2、4、8字节。在按照1字节对齐之后,打印a、b、c、d在内存上的地址:
在这里插入图片描述
可以看到,结构体首地址也就是成员a的地址是按照32字节对齐的。可以用如下的示意图表示使用__attribute__((aligned(32)))前后结构体及其成员在内存中的分布:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1543036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实现登录拦截功能

1.4、实现登录拦截功能 温馨小贴士:tomcat的运行原理 当用户发起请求时,会访问我们像tomcat注册的端口,任何程序想要运行,都需要有一个线程对当前端口号进行监听,tomcat也不例外,当监听线程知道用户想要和…

发展规划--IM系统

1、时代背景 5G应用,多终端应用,物联网应用,小程序,工业互联,大数据应用等等大前端时代的到来,程序员不能只关注crud,因为以后的服务并发量只会越来越多。 高并发架构师、大数据架构师或者说j…

Redis入门到实战-第六弹

Redis实战热身Lists篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的(采用BSD许可证),用作数据库、缓存、消息代理和流…

【基于HTML5的网页设计及应用】——随机验证码

🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL&#xff1a…

WPF---1.入门学习

学习来源 布局 wpf布局原则 一个窗口中只能包含一个元素 不应显示设置元素尺寸 不应使用坐标设置元素的位置 可以嵌套布局容器 StackPanel-->表单条件查找布局 DataGrid wpf布局容器 StackPanel: 水平或垂直排列元素,Orientation属性分别: Horizontal / Vertic…

查询正在运行的Top SQL的脚本(建议收藏)

这篇文章提供了一些现成的SQL脚本,通过查询V$SQLSTATS视图找到正在运行的TOP SQL,用于后续的优化。建议大家收藏,需要查询TOP SQL时直接复制和粘贴即可。 之前的一篇文章解释了为什么要使用V$SQLSTATS视图。 当数据库表现出各种不同的性能问…

Linux/WifineticTwo

WifineticTwo Enumeration nmap 经过使用 nmap 对常见的 1000 个端口进行扫描,并加入禁止 ping 的参数,长时间的扫描结果显示,仅有 22 和 8080 两个端口处于开放状态 ┌──(kali㉿kali)-[~/vegetable/HTB/WifineticTwo] └─$ nmap 10.10…

渗压计测量:VW-102A与WM-103型读数仪的应用与优势

在当代工程测量领域,准确监测地下水压力变化对于确保建筑结构的安全和稳定至关重要。渗压计作为一种专业的测量工具,能够精确地监测和记录地下水的压力变化,是水利工程、地下建筑、坝体安全监测等领域不可或缺的仪器。今天主要给大家介绍下读…

make menuconfig

本文不是分析Linux的make menuconfig,而是如何将Linux这套机制适配到自己的项目里。 Linux内核配置工具会使用到menuconfig。menuconfig会用到mconf、conf两个命令。这两个命令是编译内核自动生成的。网上有开源的实现,我们下载下来自己编译&#xff1a…

SQLiteC/C++接口详细介绍sqlite3_stmt类(七)

返回:SQLite—系列文章目录 上一篇:SQLiteC/C接口详细介绍sqlite3_stmt类(六) 下一篇: 无 22、sqlite3_column_database_name 用于返回结果集中指定列的数据库名称。如果结果集是由多个Join操作产生的,…

公域流量和私域流量该如何选择?

很多客户在做品牌推广的时候,都会犹豫应该把精力投放到公域流量还是做自己的私域流量。特别是现在流量为王的时代,大部分客户都在布局做公域流量,砸钱推广,直播带货各种形式进行曝光。 在无论是线上还是线下的公共领域&#xff0…

Microsoft Remote Desktop:无缝连接,高效远程工作的首选工具

随着科技的发展,远程工作已经成为了越来越多人的选择。在这样的背景下,一款高效、稳定且安全的远程桌面工具显得尤为重要。Microsoft Remote Desktop正是这样一款能够满足用户需求的远程桌面软件。 Microsoft Remote Desktop是微软开发的一款专为远程连…

38张最全计算机网络基础思维导图,值得一看!

你们好,我的网工朋友。 计算机网络基础知识点多且杂,想要系统地学习,思维导图肯定是必不可少的。 今天我给你找全了38张思维导图,帮助你轻松理清思路,快速掌握关键内容。 建议你收藏起来慢慢看,在看过之…

宋仕强说金航标kinghelm萨科微slkor都是网红品牌

宋仕强说金航标kinghelm萨科微slkor都是网红品牌,和宋仕强先生研究的“华强北”大ip一起,相互支持相互驱动,与金航标网站(www.kinghelm.com.cn)、萨科微网站(www.slkormicro.com)组合成为宣传矩…

2024/3/24--爬虫库

1.常用的爬虫库 (1)在setting的project里面点击Python Interpreter (2)常用的爬虫库有 import requests //用途:用于发送HTTP请求。from bs4 import BeautifulSoup //用于从HTML或XML文档中提取数据。import scrapy //一个功能强大的爬虫框架&#xf…

基于Java的流浪动物收容与领养网站

基于Java的流浪动物收容与领养网站的设计与实现 摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和遍及使得各种信息系统的开发成为一定。 流浪动物收容与领养管理系统,主要的模块包括首页、个人中心、用户管理、员工…

.NET分布式Orleans - 2 - Grain的通信原理与定义

Grain 是 Orleans 框架中的基本单元,代表了应用程序中的一个实体或者一个计算单元。 每个Silo都是一个独立的进程,Silo负责加载、管理和执行Grain实例,并处理来自客户端的请求以及与其他Silo之间的通信。 通信原理 在相同的Silo中&#xff0…

Vue动态设置控制表格列表展现列

最近遇到一个需求,表格列表默认不展示某一列,当我设置后可以展示该列,也可以展示和隐藏别的列,起到可以对整个表格列展示隐藏控制的效果,如下示例,默认不展示“单位名称”这一列,在我点击设置齿轮后可以看到,有“单位名称”这一列,但未打钩: 当我勾中“单位名称”,…

【解决】Unity Profiler | Sempaphore.WaitForSignal

开发平台:Unity 2022 版本以上 开发语言:CSharp 6.0 编程平台:Visual Studio 2022 关键词:Sempaphore.WaitForSignal   问题背景 开发过程中出现 Waiting to excute code… 长时间阻碍运行。使用 逐对象排查法 确认影响无法运行…

mineadmin前端安装启动

在上一篇文章中, 我们已经搭建好了后端环境并启动 mineadmin 快速安装部署(docker环境) 一、下载前端项目 1、在搭建后端时候,使用php bin/hyperf.php mine:install 的时候,有一个步骤是安装前端项目的。安装目录为&a…