c++ - 英特尔 x64 的 GCC 中指向整数的指针对齐

标签 c++ pointers alignment

我需要从某个内存位置将几个四字加在一起:

uint64_t sum2 (const char * p, size_t n)
{
    uint64_t res = 0;
    const uint32_t * q = (const uint32_t*) p;
    size_t i;
    for (i = 0; i < n; i++) res += q[i];
    return res;
}

我知道这段代码不必在任意机器上的任意 C 编译器上工作。并非每个指向 char 的指针都可以转换为指向 int 的有效指针。但是,在 Intel 上,您可以从任何地址读取 32 位值,在大多数情况下甚至没有任何性能损失,因此这段代码应该可以正常工作,而不管 p 的对齐方式如何。我的程序在 64 位 Intel Sandy Bridge 上运行,使用 GCC 4.8 使用 -msse4.2 -O3 编译。

本地址不是 4 对齐时,此代码发出 SIGSEGV。原因是循环展开四次并使用 SSE 编译。使用MOVDQA一起读取四个值,需要16位对齐。在循环之前,指针16位对齐,前提是它已经4位对齐。

如何防止 GCC 上的 SSE 优化?我确实需要添加未对齐的 32 位数字。

最佳答案

它可能会降低性能,但我认为您需要使用 memcpy 复制到正确对齐的临时文件。

uint64_t sum2 (const char * p, size_t n)
{
    uint64_t res = 0, temp;
    const uint32_t * q = (const uint32_t*) p;
    size_t i;
    for (i = 0; i < n; i++) {
        memcpy(&temp, &q[i], sizeof(*q));
        res += temp;
    }
    return res;
}

希望它不会对齐 q&q[i]。如果是这种情况,您需要自己进行地址运算。

uint64_t sum2 (const char * p, size_t n)
{
    uint64_t res = 0, temp;
    size_t i;
    for (i = 0; i < n; i++, p += sizeof(uint32_t)) {
        memcpy(&temp, p, sizeof(uint32_t));
        res += temp;
    }
    return res;
}

关于c++ - 英特尔 x64 的 GCC 中指向整数的指针对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39300708/

相关文章:

c++ - 如何在 GDI+ 中使用库存对象

c++ - 指向没有变量的方法的指针,这段代码是如何工作的?

c++ - 将二维数组指针参数分配给局部数组指针变量

javascript - 如何让我的选项卡 100% 位于顶部?

html - 对齐段落html css中的图像

c++ - 2.0 和 2.0f 之间的区别(显式 float 与 double 文字)

C++ 静态交叉编译在 LibCurl 和 OpenSSL 上失败

c++ - 科学计数法 C++ 中的字符串到双重转换

c - 从指向字符串的指针数组访问字符串的字符

css - HTML 分区对齐