C编译器如何在同一条语句中解释声明函数和变量?

时间:2018-08-15 04:32:02

标签: c pointers kernighan-and-ritchie

我遇到了K&R中的一个声明,其中在“指针”一章中一起声明了一个函数和一个变量:

double atof(), *dp;

C编译器如何处理上述声明?

2 个答案:

答案 0 :(得分:2)

声明(C17 6.7)的语法为:

declaration:
  declaration-specifiers init-declarator-list(opt) ;

其中声明说明符的一种情况是类型说明符,在这种情况下为double

进一步挖掘 init-declarator-list 会得到 init-declarator ,可以选择用逗号分隔的几个:

init-declarator-list:
  init-declarator
  init-declarator-list , init-declarator

init_declarator 依次给出 declarator ,其语法为(C17 6.7.6):

declarator:
  pointer(opt) direct-declarator

在示例中,atof()dp直接声明符,其中dp具有可选的指针语法。

这意味着atof()结束了一个函数,该函数返回double*dp指向double的指针。

(如果您想挖掘上述原始语法,则该标准的附件A会有所帮助。没有理智的人会在不查找它们的情况下记住此类内容。)


但是,实际上没有理由考虑这样糟糕的编写代码。以下是公认的不良做法:

  • 在文件范围内将函数声明写成其他地方,但写成一行。
  • 编写没有原型格式的函数声明。标准C 7.22.1.1中atof的正确原型是double atof(const char *nptr);。而double atof()表示带有任何参数的函数。根据C17 6.11.6,这是过时的样式。
  • 在一行中写多个声明。不要写double d, *dp;之类的东西,而写double d; double* dp;。已知前者会因错误声明错误类型而导致错误。另外,如果您始终拆分声明,则不必考虑写double* dp样式还是double *dp样式是否更正确。

摘要:不要阅读1970年代过时的编程书籍。尝试将K&R更新到C90的过程很草率,并且本书的许多第二版都不是1989年的最新版本。例如,过时的样式在C90 6.9.4中已经存在。因此,本书包含了在1989年已经被C标准废弃的实践!简直太恐怖了。

答案 1 :(得分:1)

在C中,逗号可以用作运算符或分隔符。就您而言,它用作分隔符。

如果您仔细阅读在线here上可用的C语法,您会发现许多使用逗号作为分隔符的用法。 用途之一如下:

init_declarator_list
    : init_declarator
    | init_declarator_list ',' init_declarator