C语言 指示内存对齐要求的编译器常数

kkbh8khc  于 2023-08-03  发布在  其他
关注(0)|答案(2)|浏览(97)

一些CPU架构(除了x86)不喜欢在未对齐的地址上阅读和写入多字节数,以至于它们在检测到这一点时引发SIGBUS异常,并迫使程序员手动按字节顺序执行所有操作。虽然在需要这种操作的平台上可能什么也做不了,但在允许非对齐访问的平台(如x86)上检查对齐并执行字节操作是愚蠢的。问题是:C/C++编译器是否定义了一个常量来表示对齐要求
目前,我正在使用这个:

#if defined(_M_IX86) | defined(__i386) | defined(__i386__) | defined(i386) | defined(_X86_)
    // Unaligned access is allowed.
#elif defined(_M_X64) | defined(__x86_64__) | defined(__x86_64) | defined(__amd64) | defined(__amd64__) | defined(_M_AMD64)
    // Unaligned access is allowed.
#else
    #define ALIGNED_ACCESS_ONLY
#endif

字符串
但它看起来太“自制”了:本文并没有指出当前硬件平台的实际属性,只是描述了我自己对x86-32和x86-64的考虑以及这些平台最流行的常量名称。

rekjcdws

rekjcdws1#

  • 从技术上讲,我并没有回答你提出的问题,但我提出了一个解决方案,以防你的问题的答案是否定的。

如果您的代码是在配置脚本的帮助下编译的,则可以测试以查看是否需要对齐访问。GNU autoconf有一个功能可以做到这一点:
http://www.gnu.org/software/autoconf-archive/ax_check_aligned_access_required.html
基本上,它编译下面的小程序,运行它,并查看结果:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  char* string = malloc(40);
  int i;
  for (i=0; i < 40; i++)
  {
    string[[i]] = i;
  }

  {
     void* s = string;
     int* p = s+1;
     int* q = s+2;

     if (*p == *q) { return 1; }
  }
  return 0;
}

字符串

xxslljrj

xxslljrj2#

我在memcpy的实现中看到过一种不需要对此进行任何检查的解决方案。基本上,您开始逐字节复制数据,直到获得所需对齐的地址倍数。
在此之后,您可以开始复制字大小的数据块,并使用对齐地址的所有好处(循环展开,矢量化......)。
不过,您将在处理大数据块时获得最佳效果。
显然,clanggcc都没有定义任何宏来通知未对齐的访问。(gcc/clang -E -dM - < /dev/null -march=native)。
您可能需要考虑的一些想法:

  • 首先减少需求:使用指针时会产生问题。尽量避免这种情况,重构你处理数据的方式。
  • asm:编写依赖于平台的asm,以便从非对齐访问加载/存储,尽管它高度依赖于您正在使用的平台。
  • SSE允许非对齐访问。

相关问题