我正在使用32位机器,所以我认为内存对齐应该是4个字节.说我有结构:
typedef struct {
unsigned short v1;
unsigned short v2;
unsigned short v3;
} myStruct;
Run Code Online (Sandbox Code Playgroud)
实际大小是6个字节,我想对齐大小应该是8,但sizeof(myStruct)返回6.
但是,如果我写:
typedef struct {
unsigned short v1;
unsigned short v2;
unsigned short v3;
int i;
} myStruct;
Run Code Online (Sandbox Code Playgroud)
实际大小是10个字节,对齐是12,这次sizeof(myStruct) == 12.
有人可以解释一下有什么区别吗?
是否可以使用std::vector自定义结构分配对齐的内存以便使用SIMD指令进行进一步处理?如果有可能,有Allocator没有人碰巧有这样的分配器,他可以分享?
以下摘录自此处
Run Code Online (Sandbox Code Playgroud)pw = (widget *)malloc(sizeof(widget));分配原始存储.实际上,malloc调用分配的存储空间足够大并且适当地对齐以容纳类型为widget 的对象
他还说,从草本植物中看到快速的pImpl,他说:
对齐.任何内存对齐.保证通过new或malloc动态分配的任何内存都可以正确地对齐任何类型的对象,但是没有动态分配的缓冲区没有这样的保证
我对此感到好奇,malloc如何知道自定义类型的对齐方式?
对于任何对象类型T,它总是sizeof(T)至少与大小一样大alignof(T)吗?
直观地看起来如此,因为即使你调整对象的对齐方式,例如:
struct small {
char c;
};
Run Code Online (Sandbox Code Playgroud)
通常情况下,它们的"大小"也会向上调整,以便在保持对齐的同时,阵列中对象之间的关系是有意义的(至少在我的测试中.例如:
struct alignas(16) small16 {
char c;
};
Run Code Online (Sandbox Code Playgroud)
两者的大小和对齐都是16.
这是Rob Walker 在这里回答的问题.
假设我声明一个类/结构,如下所示:
struct
{
char A;
int B;
char C;
int D;
};
Run Code Online (Sandbox Code Playgroud)
是否可以安全地假设这些成员将在内存中以完全相同的顺序声明,或者这是否依赖于编译器?我问,因为我一直认为编译器可以随心所欲地做任何事情.
这导致了我的下一个问题.如果上面的例子导致内存对齐问题,为什么编译器不能只是隐式地将它变成这样的东西:
struct
{
char A;
char C;
int B;
int D;
};
Run Code Online (Sandbox Code Playgroud)
(我主要是询问C++,但我也有兴趣听到C答案)
我在我的计算机(运行 Linux 的 64 位 Intel)上运行了以下程序。
#include <stdio.h>
void test(int argc, char **argv) {
printf("[test] Argc Pointer: %p\n", &argc);
printf("[test] Argv Pointer: %p\n", &argv);
}
int main(int argc, char **argv) {
printf("Argc Pointer: %p\n", &argc);
printf("Argv Pointer: %p\n", &argv);
printf("Size of &argc: %lu\n", sizeof (&argc));
printf("Size of &argv: %lu\n", sizeof (&argv));
test(argc, argv);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出是
$ gcc size.c -o size
$ ./size
Argc Pointer: 0x7fffd7000e4c
Argv Pointer: 0x7fffd7000e40
Size of &argc: 8
Size of &argv: 8
[test] Argc …Run Code Online (Sandbox Code Playgroud) 对齐对C++ 11的性能是否真的重要?
在Stroustrup的书中有一条建议,要求从最大到最小的结构中对成员进行排序.但我想知道是否有人进行了测量,以确定是否会产生任何影响,并且在编写代码时是否值得考虑.
Microsoft提供了InterlockedCompareExchange执行原子比较和交换操作的功能.还有一个内在的._InterlockedCompareExchange
在x86上,这些是使用lock cmpxchg指令实现的.
但是,通过阅读这三种方法的文档,他们似乎并不同意对齐要求.
英特尔的参考手册没有说明对齐(除了如果启用了对齐检查并且进行了未对齐的内存引用,则会生成异常)
我也查找了lock前缀,具体说明了这一点
锁定前缀的完整性不会受到内存领域的对齐方式.
(强调我的)
所以英特尔似乎认为对齐是无关紧要的.无论如何,这个操作都是原子的.
该_InterlockedCompareExchange固有的文档也只字未提对齐,但是InterlockedCompareExchange 功能指出,
该函数的参数必须在32位边界上对齐; 否则,该函数将在多处理器x86系统和任何非x86系统上表现不可预测.
什么给出了什么?对齐要求是否InterlockedCompareExchange只是为了确保该功能即使在cmpxchg指令不可用的486之前的CPU上也能正常工作?这看起来很可能基于上述信息,但在依赖它之前我想确定一下.:)
或者ISA需要对齐以保证原子性,我只是在英特尔的参考手册中找错了地方?
让我们考虑结构:
struct S1 {
int a;
char b;
};
struct S2 {
struct S1 s; /* struct needed to make this compile as C without typedef */
char c;
};
// For the C++ fans
struct S3 : S1 {
char c;
};
Run Code Online (Sandbox Code Playgroud)
S1的大小为8,由于对齐而预期.但是S2和S3的大小是12.这意味着编译器将它们构造为:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
| a | b | padding | c | padding |
Run Code Online (Sandbox Code Playgroud)
编译器可以在不破坏对齐约束的情况下将c放在6 7 …
假设我有这样的结构:
struct MyStruct
{
uint8_t var0;
uint32_t var1;
uint8_t var2;
uint8_t var3;
uint8_t var4;
};
Run Code Online (Sandbox Code Playgroud)
这可能会浪费很多(不是很多)空间.这是因为uint32_t变量的必要对齐.
实际上(在对齐结构以便它实际上可以使用uint32_t变量之后)它可能看起来像这样:
struct MyStruct
{
uint8_t var0;
uint8_t unused[3]; //3 bytes of wasted space
uint32_t var1;
uint8_t var2;
uint8_t var3;
uint8_t var4;
};
Run Code Online (Sandbox Code Playgroud)
更有效的结构将是:
struct MyStruct
{
uint8_t var0;
uint8_t var2;
uint8_t var3;
uint8_t var4;
uint32_t var1;
};
Run Code Online (Sandbox Code Playgroud)
现在,问题是:
为什么编译器禁止(按标准)重新排序结构?
如果对结构进行重新排序,我认为你没有任何方法可以用脚射击自己.