用于在 Intel Core 2 Duo 上对齐的 C 代码

C code for alignment on Intel Core 2 Duo

我得到了以下用于对齐的 c 代码

struct s *p, *new_p
p = (struct s*) malloc(sizeof(struct s) + BOUND -1);
new_p = (struct s*) (((int) p+BOUND-1) & ~(BOUND -1);

其中 BOUND 代表 32 个字节。像 Pentium II 和 III 一样,一行缓存是 32 字节,但我无法弄清楚 p 和 new_p 对齐的方式。两者对齐还是仅 new_p?

此外,对于一组关联缓存,每组有 8 个块,大小为 32 Kb,我有一个 64 B 缓存行的代码:

int *tempA, *tempB;
...
pA= (int *) malloc (sizeof(int)*N + 63);
tempA = (int *)(((int)pA+63)&~(63));
tempB = (int *)((((int)pA+63)&~(63))+4096+64)

伴随着这句话:如果你访问超过8个地址,间隔4Kb,将会有惩罚。

整体对我来说意义不大。有什么想法吗?

为什么不使用 _Alignas()(自 C11 起)?

将指针转换为 int 是对灾难的邀请(又名 未定义的行为)。想想一台 64 位机器和 32 位机器(大多数 x86 的标准)。 如果你需要对指针进行算术运算,使用uintptr_t(不过我不推荐使用intptr_t)。然而,即使在这里,值的算术仍然未定义(但对于具有单个线性地址的平台来说很可能是安全的space)。

标准说明:not cast void *malloc() 返回。

更新:

好的,让我们对上面的代码进行适当的格式化和输入:

#include <stdint.h>

// align to this boundary (must be power of two!)
#define ALIGN_BOUNDARY 64U

不要在代码中使用幻数! 2个月后你会想知道这意味着什么。

int *tempA, *tempB;

它们是如何使用的?

int *pA = malloc (sizeof(int) * N + ALIGN_BOUNDARY - 1);
uintptr_t adjA = ((uintptr_t)pA + (ALIGN_BOUNDARY - 1)) & ~((uintptr_t) (ALIGN_BOUNDARY - 1);

这只是将地址向上舍入到下一个对齐的边界(此处:64 字节)。

tempA = (int *)adjA;
tempB = (int *)(adjA + 4096 + 64)

不确定后者有什么用,但是对于给定的 malloc,如果使用相同的索引 (0..[=21=),由于访问超出分配的块,将导致灾难]) 作为 *pA.

无论如何,我都会非常非常小心地处理这段代码。它不仅看起来很糟糕 written/documented,而且似乎还包含错误。