使用C结构成员的连续内存 [英] Using Contiguous Memory of C Struct Members

查看:198
本文介绍了使用C结构成员的连续内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将其标记为重复之前,请先阅读问题。

Before you mark this as duplicate, please do read the question.

因此,这可能是一个非常愚蠢的问题,但它困扰着我。从阅读以及许多其他SO问题中,我知道由于编译器添加的填充,不能保证C中的结构体中的字段是连续的。例如,根据C标准:

So this may be a potentially very stupid question but it is bothering me. I know, from reading, as well as many other SO questions that fields in a struct in C are not guaranteed to be contiguous due to padding added by the compiler. For example, according to the C standard:


13 / 在结构对象中,非位字段成员和位字段所在的单元的地址按照声明的顺序增加。指向经过适当转换的结构对象的指针指向其初始成员(或者,如果该成员是位字段,则指向它所驻留的单元),反之亦然。在结构对象中可能存在未命名的填充,但在其开始时没有。

13/ Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

我正在编写与Unix相似的程序 readelf nm 只是为了好玩,它涉及到处理文件中特定偏移量的字节的大量工作。读取某些值。例如,目标文件的前62个字节包含文件头。文件头的字节0x00-0x04编码为一个int,0x20-0x28编码为一个指针等。但是,我在readelf.c的原始实现中注意到程序员会执行以下操作:

I was working on writing a program similar to the unix readelf and nm just for fun and it involves a lot of work with dealing with bytes at specific offsets into the file to read certain values. For example, the first 62 bytes of an object file contains the "file header". The file header's bytes 0x00-0x04 encode an int, while 0x20-0x28 encode a pointer etc. However, I noticed in the original implementation of readelf.c that the programmer does something like this:

首先,他们声明一个结构(称为ELF_H),其字段与文件头中的内容相对应(即,第一个字段是int,就像文件头中的前4个字节一样,第二个是一个char,因为elf标头中的字节0x04-0x05编码了char等)。然后,他们要做的就是将整个elf文件复制到内存中,并将指向该内存起始位置的case指针键入ELF_H类型。

First, they declare a struct (lets call it ELF_H) with fields corresponding to the things in the file header (i.e. the first field is an int just like the first 4 bytes in the file header are, the second is a char because bytes 0x04-0x05 in the elf header encode a char etc.). Then what they do is copy the entire elf file to memory and type case the pointer that points to the start of this memory into type ELF_H. Something like:

FILE *file = fopen('filename', rb);
void *start_of_file = malloc(/* size_of_file */);
fread(start_of_file, 1, /* size_of_file */,file);  // copies entire file into memory
ELF_H hdr = *(ELF_H) start_of_file;               // type case pointer to be of type struct and dereference

,然后执行此操作,只需访问每个节通过使用struct的成员变量来确定标题。因此,与其使用指针运算来获取字节0x04的内容,不如执行hdr.member2(在结构中是第二个成员,后一个是int)。

and after doing this, just access each section of the header by using the member variables of the struct. So instead of getting what is supposed to be at byte 0x04 using pointer arithmetic, they just do hdr.member2 (which in the struct is the second member followed by the first one which was an int).

如果不能保证结构中的字段是连续的,这意味着如何工作?

How is this meant to work if fields in a struct aren't guaranteed to be contiguous?

我能找到的最接近答案是此处,但在该示例中,该struct的成员属于同一类型。在ELF_H中,它们具有不同的类型。

The closest answer I could find to this was here but in that example, the members of the struct are of the same type. In the ELF_H, they are of different types.

预先感谢您:)

推荐答案


如果不能保证结构中的字段是连续的,这意味着什么?

How is this meant to work if fields in a struct aren't guaranteed to be contiguous?

标准不要求结构是连续的,但这并不意味着结构以随机或不可预测的方式进行布局。使用的特定编译器和链接器将始终按照应用程序二进制接口或ABI的指定方式以指定的方式生成二进制文件。碰巧在GNU / Linux机器上,ELF ABI与GCC布局和访问该结构的方式完全相对应。

The standard doesn't require structs to be contiguous, but this doesn't mean that structs are laid out at random or in unpredictable ways. The specific compiler and linker being used will always generate the binary in a specified way, as dictated by the Application Binary Interface or ABI. It just so happens that on a GNU/Linux machine, the ELF ABI exactly corresponds to how GCC will lay out and access that struct.

换句话说,您可以预测您描述的方法是否适用于任何给定的ABI /编译器/链接器组合。它不能保证按标准运行,但可以保证ABI的兼容性。

In other words, you can predict whether the method you describe will work for any given ABI / compiler / linker combination. It's not guaranteed to work by the standard, but it might be guaranteed to work by the compatibility of ABIs.

这篇关于使用C结构成员的连续内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆