3

C lang FAQ我发现了以下代码:

void f(ipp)
int **ipp;
{
    static int dummy = 5;
    *ipp = &dummy;
}

我测试了用-Wall -std=c11 -pedantic标志编译它,它编译时没有警告或错误。这怎么可能——在函数名和它的块之间声明的变量?

编辑

发布几个小时后,经过多次回答,我发现该问题已作为重复项关闭。我不同意关闭的决定。事实上,到目前为止,这里给出的重复问答和答案虽然大致正确,但并没有具体回答我的问题。

我的查询是关于出现函数名及其块之间的变量声明。好吧,这就是最初的 K&R 风格,但我仍然觉得声明的位置令人震惊。阅读了描述 ANSI C89 的 K&R 第二版书后,我意识到以前的风格允许以不同的方式声明函数参数,但是 AFAIK 那本书没有显示以这种方式进行的声明。也许确实如此,但我已经忘记了。

我相信最好单独提出关于这个特定问题的问题,以防其他人在未来被它抛出。我的问题应该代表任何能够阐明如何决定允许在这个奇怪的位置声明参数的人。你从 C 和所有受 C 启发的语言中得到的印象是,在标记和它的大括号之间没有任何东西。我的问题提请注意一个重要的例外,即使它是 30/40 岁,也应该强调它的基本原理。

编辑 2

我现在发现 C++ 语法允许在函数名和它的块之间添加一个标记。即便如此,介于两者之间的整个声明行的想法更为严重,值得向 C 新手指出,这是他们可能遇到的一个怪癖。我查过,K&R 第二版书确实没有明确提到这一点。

4

4 回答 4

5

它不是任何变量,而是函数参数。只是另一种编程风格,称为 K&R 风格。

对此进行一些额外的阅读

于 2019-11-14T13:04:41.283 回答
3

很长一段时间以来,此语法已被弃用,但在 C17 中它仍然有效。这个特性的移除最近已经被 C2x 投票,见第 6.30 点:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2451.pdf

于 2019-11-14T13:19:20.747 回答
1

通常,函数定义在 C 标准中定义如下

function-definition:
    declaration-specifiers declarator declaration-listopt compound-statement

declaration-list:
    declaration
    declaration-list declaration

这种包含 的函数定义declaration-list被命名为具有标识符列表的函数定义,与具有参数类型列表的函数定义相反。

所以在函数声明器中使用了一个标识符列表

void f(ipp)
       ^^^^

需要在函数体之前声明

void f(ipp)
int **ipp;
^^^^^^^^^

这是一种旧式的函数定义,不推荐使用,因为此类定义不提供编译器可以检查的函数原型。

于 2019-11-14T13:27:05.510 回答
1

来自 C11 标准:

6.7.6 声明符:
1.direct-declarator(参数类型列表)
2.direct-declarator(标识符列表)

如您所见,该标准指定了两种声明函数的方式。

第一个涉及类型化参数,其中每个参数都被赋予特定类型。

第二个涉及一个标识符列表,其中在括号内提供参数名称而没有给出数据类型。

因此,您的代码是有效的 C11 并且可以按预期正常编译。

于 2019-11-14T13:28:40.210 回答