有没有人有书面证据来保证函数中参数的定义方式与普通变量声明相同?

Does anyone have the written evidence which assure that the way parameters are defined in a function is the same as normal variable declarations?

本文关键字:方式 变量 声明 定义 参数 证据 没有人 函数      更新时间:2023-10-16

通过"正态变量声明",我假设

声明如下所示。
int a = 3;

如果你定义一个函数的参数,你会这样写:

void func(int a) {
<statement>
}

让我们假设一个更复杂的情况。当你通常声明一个指向函数的指针数组时,你将写入

int (*p[3])(int, double);

如果你想把这个数组设置为函数参数,你会写

void func(int (*p[])(int, double)) {
<statement>
}

现在我发现,无论如何,这两种方式看起来几乎是一样的。但是,我找不到什么样的"书面证据"可以保证这一规则。换句话说,当我编写一个超级复杂的法线声明时,我凭什么可以相信我能够像刚才在正常声明对象时使用的方式将对象设置为函数参数?据我所知,这个规则是正确的,但似乎没有证据,尽管我访问了很多英文和日文网站,甚至阅读了C++11草案。

有人有证据吗?

C 语言答案:

常规变量声明和参数声明并不总是相同的。这是由 C 标准 C11 6.7.6.3"函数声明符"规定的,我们可以在其中阅读

参数声明中唯一应出现的存储类说明符是寄存器。

仅此一项就是一个主要区别。我们不能有staticextern的参数 - 它们只能是auto(默认)或register.

将参数声明为"类型数组"应调整为"限定指针到 类型'',

这意味着声明为数组的所有参数都将调整为指向该数组的第一个元素的指针。这就是您的示例中发生的情况!

int (*p[3])(int, double);
int (*p[])(int, double);
int (*p[666])(int, double);

当作为参数写入函数时,所有元素都会被调整("衰减")为指向第一个元素的指针。也就是说,指向函数的指针指向接受 int、double 和返回 int 的函数的指针。又名这个怪物:int (**p)(int, double);

您可以侥幸使用空[],因为编译器不关心数组边界。这实际上会创建一个不完整类型的数组(这是不允许的),但编译器将其调整为指向第一个元素的指针,因此数组大小无关紧要,因为该部分无论如何都会在"调整"期间丢失。

将参数声明为"函数返回类型"应调整为"指向 函数返回类型'',如 6.3.2.1 中所示。

这意味着,如果你有一个疯狂的想法,将整个函数传递给另一个函数,它就会被调整为一个函数指针。这意味着像void func( int p (int, double) )这样的疯狂代码实际上是有效的,等同于void func( int (*p)(int, double) )。这是函数参数的特殊情况。

免责声明这个答案是在C++是问题的唯一语言标签时写的。

当您通常声明指向函数的指针数组时,您将 写

int (*p[3])(int, double);

否。这是一个错误的前提。

你这样写:

using My_callback_t = int (int, double);
std::array<My_callback_t*, 3> p;
// or
std::array<std::function<My_callback_t>, 3> p;

或者使用std::vector而不是std::array以获得更大的灵活性。

在我看来,问题的其余部分变得毫无意义,但为了您的娱乐,这就是您要求的怪物:

void func(int (*(&p)[3])(int, double))
{
}

以防万一我不够清楚:不要写这个!!

void func(int (*(&p)[3])(int, double))
^                       p
^                        is a reference
^                     to an array
^                    of 3 elements of type
^                          pointer
^                 to function
^~~~~~~~~~~~     receiving 2 params of type int and double
^~~                             and returning int
^~~~~~~~~~~~~~~~~~~~~~~~~~      Kill. Me. Now!