c/c++--字节对齐(byte alignment)

48 篇文章 0 订阅
31 篇文章 1 订阅

1. 默认字节对齐

  • 在所有结构体成员的字节长度都没有超出操作系统基本字节单位(32位操作系统是4,64位操作系统是8)的情况下
    按照结构体中字节最大的变量长度来对齐;
  • 若结构体中某个变量字节超出操作系统基本字节单位
    那么就按照系统字节单位来对齐

注意:
并不是32位就直接按照4个字节对齐,64位就按照8个字节对齐。

2. 为什么存在字节对齐

2.1 了解 CPU 一次读取内存数

CPU 一次能读取多少内存要看数据总线是多少位

  • 如果是16位,则一次只能读取 2 个字节
  • 如果是32位,则可以读取 4 个字节,并且 CPU 不能跨内存区间访问

例子:

假设有这样一个结构体如下:

struct st3
{
    char a;
    int b;
};
//在32位系统下,它就应该是8个字节的。

假设地址空间是类似下面这样的:
在这里插入图片描述

  • 在没有字节对齐的情况下

    1. 变量 a 就是占用了 0x00000001 这一个字节,而变量b则是占用了 0x00000002~0x000000005 这四个字节
    2. 此时 cpu 如果想从内存中读取变量 b,首先要从变量 b 的开始地址 0x00000002读到 0x0000004,然后再读取一次 0x00000005 这个字节,相当于读一个 int,cpu 从内存读取了两次
  • 如果进行字节对齐的话

    1. 变量 a 还是占用了 0x00000001 这一个字节,而变量 b 则是占用了 0x00000005~0x00000008 这四个字节
    2. 此时 cpu 要读取变量 b 的话,就直接一次性从 0x00000005 读到 0x00000008 ,就一次全部读取出来了。

总结:

  • 字节对齐的根本原因其实在于 cpu 读取内存的效率问题,对齐以后,cpu读取内存的效率会更快。
  • 对齐的时候 0x00000002~0x00000004 这三个字节是浪费的,所以字节对齐实际上也有那么点以空间换时间的意思,具体写代码的时候怎么选择,其实是看个人的。

3. 编码时手动设置对齐

两种。

3.1 代码里添加预编译标识 pragma pack(n)

3.1.1 用法

  • 使用预编译指令 #pragma pack (n) 来告诉编译器,使用我们指定的对齐值来取代缺省的。
  • 对齐的算法: 随编译器变化
//用法如下
#pragma pack(n)//表示它后面的代码都按照n个字节对齐
struct st3
{
    char a;
    int b;
};
#pragma pack()//取消按照n个字节对齐,是对#pragma pack(n)的一个反向操作

3.1.2 例子

#include <stdio.h>

#pragma pack(1)//表示它后面的代码都按照n个字节对齐
struct st3
{
    char a;
    int b;
};
#pragma pack()//取消按照n个字节对齐,是对#pragma pack(n)的一个反向操作

#pragma pack(2)//表示它后面的代码都按照n个字节对齐
struct st4
{
    char a;
    int b;
};
#pragma pack()//取消按照n个字节对齐,是对#pragma pack(n)的一个反向操作

int main()
{
   	
    printf("%d\n",sizeof(struct st3) );
    printf("%d\n",sizeof(struct st4) );
	
   	return 0;
}

在这里插入图片描述

3.2 定义结构体时指定__attribute__((packed))

3.2.1 用法

  • __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。这个功能是跟操作系统没关系跟编译器有关.
//用法如下
struct bbb
{
   char a;
   int b;
}__attribute__((packed));//直接按照实际占用字节来对齐,其实就是相当于按照1个字节对齐了
//这里计算sizeof(st3)=5

3.2.2 例子

#include <stdio.h>

struct st3
{
   char a;
   int b;
}__attribute__((packed));

struct __attribute__((packed)) st4
{
	int b;
	char a;
};

int main()
{
   	
    printf("%d\n",sizeof(struct st3) );
    printf("%d\n",sizeof(struct st4) );
	
   	return 0;
}

在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这个错误提示是因为 `addWidget()` 方法要求传入的是 `QWidget` 类型的对象,而 `Gauge` 不是 `QWidget` 的子类,无法直接添加到布局中。 为了解决这个问题,可以使用 `QChartView` 类将 `Gauge` 包装成 `QWidget`,然后再将其添加到布局中。具体实现代码如下: ```python import sys import random from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QChartView from PyQt5.QtCore import QTimer from pyecharts.charts import Gauge, Bar from pyecharts import options as opts from PyQt5.QtChart import QChart class GaugeChart(QChartView): def __init__(self, gauge): super().__init__() self.chart = QChart() self.setChart(self.chart) self.setRenderHint(QPainter.Antialiasing) self.chart.legend().hide() self.chart.addSeries(gauge) self.chart.createDefaultAxes() self.chart.setTitle(gauge.options['title'].opts['title']) class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): # 创建垂直布局 vbox = QVBoxLayout(self) # 创建仪表盘对象 gauge = Gauge() gauge.add("", [("Value", 0)]) gauge.set_global_opts(title_opts=opts.TitleOpts(title="Gauge Demo")) gauge_chart = GaugeChart(gauge) # 创建柱状图对象 bar = Bar() bar.add_xaxis(["A", "B", "C", "D", "E"]) bar.add_yaxis("Data", [0, 0, 0, 0, 0]) # 将仪表盘和柱状图添加到布局中 vbox.addWidget(gauge_chart) vbox.addWidget(bar) # 创建定时器,每隔1秒更新数据 self.timer = QTimer() self.timer.timeout.connect(self.updateData) self.timer.start(1000) # 设置窗口大小和标题 self.setGeometry(300, 300, 300, 200) self.setWindowTitle('Dashboard Demo') self.show() def updateData(self): # 更新仪表盘数据 value = random.randint(0, 100) self.gauge_chart.chart.series()[0].setData([value]) # 更新柱状图数据 data = [random.randint(0, 100) for i in range(5)] self.bar.render_notebook().add_yaxis("Data", data, is_update=True) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_()) ``` 其中,`GaugeChart` 类继承自 `QChartView`,并将传入的 `Gauge` 对象添加到 `QChart` 中,然后再将 `GaugeChart` 对象添加到布局中。在更新数据时,需要使用 `setData()` 方法更新仪表盘的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值