3

在 C 中,使用 MSVC 和/或 GCC,是否可以控制函数参数的对齐方式?

例如

int main()
{
  __declspec( align(64) ) unsigned long long int
    test = 5;
  my_function_call( test );
  return( EXIT_SUCCESS );
}

void my_function_call( unsigned long long int fc_test )
{
  return;
}

我希望实现的是 fc_test 是 64 字节对齐的。

AFAICT,这是不可能的,但寻求确认/否认。

4

2 回答 2

3

当 my_function_call 被调用时,它被传递了一份测试。它本身没有通过测试,因此测试的对齐是无关紧要的。对齐属性是测试对象的属性,而不是其值。

参数以平台指定的方式传递。通常,小参数在寄存器中传递。在大多数机器上,寄存器是不属于内存的特殊硬件,因此它们没有地址,因此没有对齐。

如果参数很大,平台规范可能会指定它在内存中传递。然后调用函数的工作是将 test 的副本放入内存并将其地址传递给被调用函数,并让被调用函数使用该地址来检索副本。编译器可能会对临时副本的对齐方式产生一些影响,但我不知道有任何编译器会这样做。

如果出于某种原因,您希望向被调用函数传递一个对齐的地址,那么不要传递 test 的值,而是传递其地址或副本的地址(这也作为对齐属性)。此外,如果您要传递对齐的地址并希望被调用的函数知道它是对齐的,则将函数的参数声明为指向具有对齐属性的类型的指针。(这样做的语法取决于编译器,因为它不是标准 C 的一部分。我怀疑这样做的一种方法是使用 typedef 定义一个类型,并在 typedef 中包含对齐属性,然后声明函数参数成为该类型的指针。)

您不应该无缘无故地关注对象的对齐方式。

于 2012-07-15T12:06:07.603 回答
-1

在 x64 上,对齐是 16 个字节。

在 ARM 上,以 8 个字节对齐。

在 x86 上,对齐是 4 个字节。如果将堆栈上的变量按值传递给将执行连续双字比较和交换的函数,则可能会出现未对齐和段错误。我认为您需要传递变量的地址,或者定义一个本地变量并复制参数。

似乎无法用 MSVC 控制。GCC 显然确实尊重堆栈变量定义对齐限定符(!)

于 2012-07-15T15:27:31.827 回答