C: 'const' 限定符在参数列表中的含义与 typedef 用法

Dan*_*iel 2 c constants

当使用 typedef 和附加限定符时,参数列表的解析如何工作?它的工作方式是否类似于文本替换,类似于#define?

\n

例子:

\n
typedef struct Parameters_t * Parameters_pot;\nf(const Parameters_pot pars)\xc2\xa0\nf(Parameters_pot const pars)\xc2\xa0\n
Run Code Online (Sandbox Code Playgroud)\n

两个函数声明中参数列表中的“const”限定符是否与数据类型相关,这意味着指针指向常量结构?\n或者“const”的位置是否重要,并且在第一个函数声明中“const” ' 意味着结构体对象是常量,而在第二个声明中则意味着指针是常量?

\n

Lun*_*din 7

它不是文本替换。这正是为什么将指针或数组隐藏在 a 后面typedef被认为是非常糟糕的做法的原因。这里的两个例子都相当于:

f(struct Parameters_t * const pars)

自从有人提出要求后,我们才尝试解释一下正式的律师语言:

C17 6.7.8 规定 typedef 的形式为typedef T type_ident;其中type_ident是类型名称“其类型由声明说明符指定T”。说明符复数。为了理解这一点,我们必须回到关于“声明符”和“声明说明符”的 6.7 和 6.7.6。

6.7.6 说每个声明都可以说由T D1声明T说明符和D1声明符组成。

  • “声明说明符”是您可以在声明中的标识符前面编写的所有内容,包括存储类说明符(static等)和类型限定符(const等),当然还有类型说明符(int等)。其中几个可以选择存在于同一声明中。

    除了存储类说明符之外,存储类说明符作为一种特殊情况永远不能相互组合(6.7.1)。碰巧,它typedef被视为存储类说明符,因此我们不能statictypedef.

  • “声明符”包含标识符以及数组符号等。它可以选择包含*for 指针。这里重要的部分是*属于声明者。

    正式语法(6.7.6)如下:

    声明符:
    指针opt直接声明符
    ...
    指针:
    * 类型限定符列表opt

回到typedef T type_ident;,然后是T属于该类型的所有内容,包括使用的任何限定符、指针语法、数组语法等。

因此,我们应该编写类似const T, then 的const内容来应用于整个类型T。现在,如果我们有“T”,例如const int*“指向 const int 的指针”,那么const T将创建一个const int* const“指向 const int 的 const 指针”。

如果T是一个函数,那么它将尝试声明一个无效的“const 函数”。等等。


因此,对于您的示例typedef struct Parameters_t * Parameters_pot;const应用于类型struct Parameters_t *

因此f(const Parameters_pot pars)相当于f(struct Parameters_t * const pars).

f(Parameters_pot const pars)也具有相同的等效含义,原因与int constconst int等效 - 大多数时候未指定声明说明符可能出现的顺序。