首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >打包或不打包只包含数组的结构

打包或不打包只包含数组的结构
EN

Stack Overflow用户
提问于 2015-08-17 16:11:53
回答 2查看 157关注 0票数 2

实验:让我们在c/c++中声明一个SHA-512摘要容器(使用GCC):

代码语言:javascript
复制
#define DIGEST_LENGTH 512
struct Digest {
  uint32_t bits[DIGEST_LENGTH / 8 / sizeof(uint32_t)];
} __attribute__((packed));

让我们不要争论uint32_t数组的选择,而不是char数组。甭管他们。

然后,我们可以以如下方式从工作缓冲区读入摘要:

代码语言:javascript
复制
Digest digest;
......
memcpy(&digest, buffer, sizeof(Digest));

类似地,我们可以将摘要写入工作缓冲区:

代码语言:javascript
复制
memcpy(buffer, &digest, sizeof(Digest)); //Assuming sufficient buffer size

我的问题:

打包的属性是否是size or (Digest)总是返回正确大小(= 512位或64字节)的充分必要条件?

摘要->bitsi是所有体系结构上的一个安全操作,而我们保留这个填充属性吗?

我们能否在保持容器不透明的同时简化表示?

如果我们保留代理,是否需要支付运行时间的罚款?

我知道还有其他关于打包属性的问题,但我的问题是专门针对包含单个基本类型数组的结构。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-17 16:42:50

打包的属性是否是size or (Digest)总是返回正确大小(= 512位或64字节)的充分必要条件?

这就足够了。

摘要->bitsi是所有体系结构上的一个安全操作,而我们保留这个填充属性吗?

我想你不懂__attribute__((packed))。下面是实际做什么。

在结构声明中使用打包时,它将压缩其字段,从而使sizeof( structure ) == sizeof(first_member) +.+ sizeof(last_member)。

下面是上述状态((打包))在嵌套的结构数组上?的资源的url

编辑:

当然是安全的。Packing定义内存中的布局,但不要担心,因为访问特定数据类型是由编译器处理的,即使数据对齐有误。

我们能否在保持容器不透明的同时简化表示?

是的,您只需定义一个简单的缓冲区uint32_t bits[LENGTH];,它将以同样的方式为您工作。

如果我们保留代理,是否需要支付运行时间的罚款?

一般来说,是的。Packing强制编译器在成员之间的数据结构中不执行填充。数据结构中的填充使得物理对象更大,但是对奇异字段的访问更快,因为它只是读取操作,例如不需要读取、掩码和旋转。

请检查下面这个非常简单的程序,显示包装对结构尺寸的影响。

代码语言:javascript
复制
#include <stdio.h>
#include <stdint.h>

#pragma pack(push, 1) 
typedef struct _aaa_t {
  uint16_t a;
  uint8_t b;
  uint8_t c;
  uint8_t d;
} aaa_t;
#pragma pack(pop)

typedef struct _bbb_t {
  uint16_t a;
  uint8_t b;
  uint8_t c;
  uint8_t d;
} bbb_t;

int main(void) {
    aaa_t a;
    bbb_t b;
    printf("%d\n", sizeof(a));
    printf("%d\n", sizeof(b));
    printf("%p\n", &(a.a));
    printf("%p\n", &(a.b));
    printf("%p\n", &(a.c));
    printf("%p\n", &(a.d));
    printf("%p\n", &(b.a));
    printf("%p\n", &(b.b));
    printf("%p\n", &(b.c));
    printf("%p\n", &(b.d));
    return 0;
}

程序输出:

代码语言:javascript
复制
5
6
0xbf9ea115
0xbf9ea117
0xbf9ea118
0xbf9ea119
0xbf9ea11a
0xbf9ea11c
0xbf9ea11d
0xbf9ea11e

Explanation:

代码语言:javascript
复制
Packed:
     ____________ _______ _______ _______ _______
    |            |       |       |       |       |
    | 0xbf9ea115 | msb_a | lsb_a | lsb_b | lsb_c |
    |____________|_______|_______|_______|_______|
    |            |       |
    | 0xbf9ea119 | lsb_d |
    |____________|_______|

Not Packed:
     ____________ _______ _______ _______ _______
    |            |       |       |       |       |
    | 0xbf9ea11a | msb_a | lsb_a | lsb_b | lsb_c |
    |____________|_______|_______|_______|_______|
    |            |       |       |
    | 0xbf9ea11e | lsb_c |  pad  |
    |____________|_______|_______|

编译器这样做是为了生成比没有填充和内存对齐优化的代码更快地访问数据类型的代码。

您可以在这个链接 演示程序下运行我的代码

票数 1
EN

Stack Overflow用户

发布于 2015-08-17 17:39:52

结构只有一个成员,所以“打包”是没有意义的。成员之间没有填充,因为没有其他成员。

您可能希望打包数组,但这是不必要的,因为uint32_t是一种精确的大小类型。(它不需要存在,但是对于缺乏uint32_t的体系结构来说,这个问题是无关紧要的。)

因此,如果您有一些外部中心的48位体系结构,其中每个"word“由四个可寻址的12位”字节“组成,那么您可能有一个编译器,其中一个int是三个”字节“,有四个字节对齐,但是您不会有一个uint32_t,因为int类型是36位,而不是32位,和(C99§7.20.1.1,这是C++11中引用的):

intN_t名称指定一个带符号整数类型,宽度为N,无填充位,以及两个补码表示形式。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32055032

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档