C语言 声明符和直接声明符的区别是什么?

u3r8eeie  于 2023-02-03  发布在  其他
关注(0)|答案(3)|浏览(216)

作者Brian W. Kernighan和Dennis M.里奇在《C编程语言,第二版》中讨论了 declaratorsdirect-declarators。讨论从书中第122页的 dcldirect-dcl 开始。请你用一种容易理解的方式解释一下declarator和direct-declarator之间的区别好吗?什么使它 direct
同样,在第225页
这里的直接声明符是一个标识符或一个带括号的标识符。特别是,它不能通过typedef来实现函数类型。
在我看来,声明符是变量或函数的声明,在“T D”中,T部分指定其说明符和类型,D部分指定标识,即变量或函数的唯一标识名,这与语言的语法有关。

  • declarator* 是不是间接的,因为它们没有被指定为直接的,如 direct-declarator 中那样?
wgxvkvu9

wgxvkvu91#

即使是第二版的K&R更多的是历史的兴趣,这些天比实际的兴趣。
尽管如此,术语“declarator”和“direct declarator”在当前的C语言规范中仍在使用。语言规范是这样描述前者的:
每个声明符声明一个标识符,并Assert当与声明符形式相同的操作数出现在表达式中时,它指定具有声明说明符所指示的作用域、存储持续时间和类型的函数或对象。
(C17第6.7.6/2段)
由此可见,“声明说明符”与“声明符”是分开的。事实上,声明符是声明的一部分,它指定要声明的是什么。
“直接声明符”是声明符的子集。“直接”与“间接”形成对比,如在指针中。例如,给定

int i;
int *p;

i*pp在语法上都是声明符,但其中只有ipdirect 声明符,只有i*pfull 声明符,它们不作为另一个声明符的一部分出现(如声明符p那样)。
它比这更复杂--例如,将 any 声明符包含在圆括号中会产生一个直接声明符,即使其本身并不是一个直接声明符。
总的来说,这是一个语法上的区别,除非你在为C语言编写解析器,否则你可能不需要太担心。如果你在为C语言编写解析器,那么你真的需要看看形式化的语法描述。

lc8prwob

lc8prwob2#

语法需要 direct-declarator 标记来指定优先级。实际上,* foo [ 3 ]必须被分析为 declarator(即*)后跟 direct-declarator(即foo [ 3 ])。如果语法没有分隔 declaratordirect-declarator,可能不清楚这是X1 M3 N1 X之后的X1 M4 N1 X组合在一起还是X1 M5 N1 X组合在一起之后的X1 M6 N1 X。
语法规定 declarator 为:

    • 指针 opt 直接声明符 *

其中,* 指针 * 是*,后跟可选限定符(如const),* 直接声明符 * 是以下内容之一:

    • 标识符 *
  • ( * 声明符 * )
    • 直接声明符 * [ * 类型限定符列表 opt 赋值表达式 *opt ]
    • 直接声明符 * [static * 类型限定符列表 opt 赋值表达式 * ]
    • 直接声明符 * [ * 类型限定符列表 * static * 赋值表达式 * ]
    • 直接声明符 * [ * 类型限定符列表 *opt * ]
    • 直接声明符 * ( * 参数类型列表 * )
    • 直接声明符 * ( * 标识符列表 * 选项)

因此,给定* foo [ 3 ],我们必须将其作为声明符,*表示 pointerfoo [ 3 ]表示 direct-declarator。无法将*放在 direct-declarator 的开头。因此,* foo [ 3 ]必须声明一个3个指针的数组,而不是指向3个元素的数组的指针。
如果 declaratordirect-declarator 的选项被合并到一个语法标记中,那么解析将是不明确的,您可以将其解析为* foo [ 3 ],因为* foo是一个声明符,后跟[ 3 ],这不是我们想要的。
名字没有什么重大意义;我们只需要为额外的标记取另一个名字。在C语法中有这样的其他例子。值得注意的是,表达式语法从 expression 开始,然后经过一系列的 assignment-expressionconditional-expressionlogical-OR-expression,等等。这些名字与它们所涉及的操作符相关联,直到您到达 primary-expression。这与 direct-declarator 有一些语义相似性,表明它们都是本着“好的,我们到达了这个语法链的底部,这里是primary/direct标记”的精神命名的。

zlhcx6iw

zlhcx6iw3#

不严格地说,声明符是一个完整的声明,而直接声明符要么是一个标识符本身,要么是一个标识符后跟[](使其成为一个数组)或()(使其成为一个函数或函数指针)。
这些术语的完整定义可以在C11 standard:的第6.7.6p1节中的声明符语法中找到。
声明者:

  • 指针直接说明符

直接声明符:

  • 识别符
  • 声明符)
  • 直接声明符[类型限定符列表赋值表达式opt ]
  • 直接声明符[static类型限定符列表停止赋值表达式]
  • 直接声明符[类型限定符列表static赋值表达式]
  • 直接声明符[类型限定符列表*]
  • 直接声明符(参数类型列表)
  • 直接说明符(标识符列表)

指针:

  • *类型限定符列表
  • *类型限定符列表指针

类型限定符列表:

  • 类型限定符
  • 类型限定符列表类型限定符

参数类型列表:

  • 参数表
  • 参数列表,...

参数列表:

  • 参数说明
  • 参数列表,参数声明

参数声明:

  • 说明说明符
  • 声明说明符抽象声明符opt

相关问题