Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C在内存中对齐x86变量而不使用struct_C - Fatal编程技术网

使用C在内存中对齐x86变量而不使用struct

使用C在内存中对齐x86变量而不使用struct,c,C,我在基于x86的CPU上使用C。 有很多文章解释了如何使用structs和#pragma pack指令对齐内存中的变量。只要您愿意使用structs,这一切都很好 我正在寻找一种方法来确保内存中变量的对齐(顺序和大小),而不使用struct 有什么办法吗 以 #pragma (push) **#pragma "anyalignment directive"** int a; byte b; long l; #pragma (pop) 如果您使用的是GCC或Clang,则如下所示: int x

我在基于x86的CPU上使用C。 有很多文章解释了如何使用structs和#pragma pack指令对齐内存中的变量。只要您愿意使用structs,这一切都很好

我正在寻找一种方法来确保内存中变量的对齐(顺序和大小),而不使用struct

有什么办法吗

#pragma (push)
**#pragma "anyalignment directive"**
int a;
byte b;
long l;
#pragma (pop)

如果您使用的是GCC或Clang,则如下所示:

int x __attribute__((aligned(16)));
int a __attribute__((aligned(16)));
byte b __attribute__((aligned(2)));
long l __attribute__((aligned(32)));

在MSVC中:

__declspec(align(16)) int x;

使用GCC属性,您可以确保每个变量的对齐方式如下:

int x __attribute__((aligned(16)));
int a __attribute__((aligned(16)));
byte b __attribute__((aligned(2)));
long l __attribute__((aligned(32)));
但是,你为什么需要这个?编译器可以按照自己认为合适的方式对声明进行重新排序(与结构成员不同,不要求变量相邻,甚至不要求变量位于内存中)


此外,使用指针跨越这些变量的边界将导致未定义的行为。您不能假定
b
紧跟在
a
之后,并且它们之间会有一个确定大小的间隙。

如果不使用
struct
,就没有标准的方法来强制内存中的分配顺序。您必须使用非标准语法在固定地址分配变量

至于对齐,您可以使用标准的C
\u Alignas
关键字强制进行比默认对齐更宽的对齐。例如:

#include <stdio.h>

// force 16 byte alignment:
int _Alignas(16) x;
int _Alignas(16) y;
int _Alignas(16) z;

int main (void)
{
  printf("%p\n", (void*)&x);
  printf("%p\n", (void*)&y);
  printf("%p\n", (void*)&z);
  return 0;
}

16字节的对齐要求已得到满足,但正如我们所见,这并不影响分配顺序。

编译器通常负责内存对齐。要执行类似于所需的操作,必须使用特殊的编译器指令来限定变量对齐。它们可以是MSVC的
\uuuuu declspec
,或者GCC的
\uuuu attribute\uuuuuu
。为什么要问这个问题?你应该解释一下!?您可以对GCC使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
。原因是我想通过复制内存中的一个区域(起始地址和大小)来创建一组变量的备份(快照),而不考虑该区域中的变量类型。同样的代码也可以在时间敏感的ARM环境中运行。通过结构访问变量不是一个选项,因为我们不确定编译器(在ARM上)如何翻译它。在x86环境中,执行时间并不那么关键。谢谢您的回答。我需要确保所有变量在每次编译时都具有相同的顺序,因此这可能对我不起作用。@J.Ens简单:使用struct.Hi Lundin,是的,使用struckt,一切正常。但我正在寻找一种不使用结构的方法…。@J.Ens我知道。请参阅此答案的第一句。如果你正在寻找一个非标准的解决方案,那么你需要编辑你的问题,并告诉你使用的是哪种特定的编译器。对不起,我有点遗漏了这一部分。我正在使用Visual Studio 2012编译器for x86 ArchitectureAnks为您输入。我想备份整个内存区域(例如,假设我有一个包含大约80个变量的状态机。现在我想能够拍摄所有这些变量的快照,并在一段时间内将状态机恢复到完全相同的状态)。当然,我可以根据每个变量的名称对其进行打包,但这在维护/扩展方面不是很方便。此外,我可以使用结构,这将适用于x86环境。但同样的代码也在高实时环境(ARM)中运行,结构在访问其中的成员时有额外开销的风险(取决于编译器如何处理)。