对 C 中一个元素的数组执行结构的 typedef 可能产生的副作用

Possible side effects of doing a typedef of a struct to an array of one element in C

我看到了这段代码。

typedef __mpz_struct MP_INT;
typedef __mpz_struct mpz_t[1];

这里的结构 __mpz_struct 是一个类型定义为单个元素数组的结构。我理解这是C中通过引用传递的技巧。然后 mpz_t 被用作声明变量并将它们作为参数传递给函数的类型。另外,还有一条评论

/*
  MP_INT*, MP_RAT* and MP_FLOAT* are used because they don't have side-effects
  of single-element arrays mp*_t
*/

他们说的是什么副作用?

看看这个示例代码

typedef char type24[3];

与您的相同,但众所周知的数据类型 'char' 代替了您的结构 __mpz_struct 类型。

above type def 的意思是,我使用上面的 typedef 来表示 char[3]。

因此在您的示例代码中,

typedef __mpz_struct mpz_t[1];

mpz_t 应该是 __mpz_struct 类型。

我看到你的问题分为两个部分。第一部分,typedef 如何将参数传递给函数,最好用一个例子来说明。没有它,我将不得不猜测一下。

在 C 函数声明中,an array parameter is equivalent to a pointer。这就是为什么你看到(例如)等同于主要功能,

int main(int argc, char **argv)

int main(int argc, char *argv[])

同样,如果要声明程序中的函数

int func(__mpz_struct *arg)

相当于

int func(__mpz_struct arg[])

因此

int func(mpz_t arg)

此外,在调用方,如果您有一个类型为 mpz_t 的变量,因此是数组,并将其传递给一个函数,则“pointer decay”会生效:在一个表达式,如果你使用一个数组(的名称),它 "decays" 变成指向它的第一个元素的指针。 这样你就可以调用函数:

mpz_t value;
func(value);

当然,要在API函数之外修改这些mpz_t对象,你还是要了解它们的本质。

你说的副作用,我也要猜。可能这意味着您必须意识到您正在使用函数内部的指针。最好使用指针语法使其显式化。

将数组传递给函数让数组衰减到指向它的第一个元素的指针。

可以通过将 Address-Of 运算符 & 应用于与数组元素类型相同的简单变量来达到相同的效果。

示例:

struct S
{
   int i;
   float f;
};

这个

void set_S(struct S * ps)
{
  ps->i = 40;
  ps->f = 2.;
}

相当于

void set_S(struct S ps[1])
{
  ps->i = 40;
  ps->f = 2.;
}

相当于

void set_S(struct S * ps)
{
  ps[0].i = 40;
  ps[0].f = 2.;
}

相当于

void set_S(struct S ps[1])
{
  ps[0].i = 40;
  ps[0].f = 2.;
}

单元素数组方法:

typedef struct S Array_of_S_with_size_1[1];

int main(void)
{
  Array_of_S_with_size_1 array_of_S_with_size_1;
  array_of_S_with_size_1[0].i = 0;
  array_of_S_with_size_1[0].f = 0.;

  set_S(array_of_S_with_size_1);

  ...
}

以上 main() 提供与以下相同的功能:

int main(void)
{
  struct S s;
  s.i = 0;
  s.f = 0.;

  set_S(&s);

  ...
}

我没有看到使用“One-Element-Array”方法有任何好处。如果 &-键在键盘上坏了,可能会有一个预期……;-)

您可以将 MP_INT 分配给另一个,但不能将 mpz_t 分配给另一个,因为没有为数组定义分配。如果你不希望你的客户分配变量而不是你的方法(可能会做内存管理和东西)这就是你的技巧。