指针声明符的 C 标准描述是否有错误?
Is there a mistake in the C standard description of pointer declarators?
C 2018 6.7.6.1 1 说:
If, in the declaration “T D1”, D1 has the form
* type-qualifier-listopt D
and the type specified for ident in the declaration “T D” is
“derived-declarator-type-list T”, then the type specified for ident
is “derived-declarator-type-list type-qualifier-list pointer to T”.
For each type qualifier in the list, ident is a so-qualified pointer.
这道题是关于最后一句话的,但我们先完成第一句。
考虑声明 int * const * foo
。这里T是int
,D1是* const * foo
,type-qualifier-list 是 const
,D 是 * foo
.
那么T D是int * foo
,并且为ident指定“指向int
的指针”foo
,所以 derived-declarator-type-list 是“指针”。 (标准中没有对 derived-declarator-type-list 的公开解释,但是 6.7.8 3,讨论 typedef
,说它“由声明符指定D.”)
将这些代入第一句的最后一个子句告诉我们 T D1 指定 foo
的类型是“指向 const
的指针int
”。目前还好。
但是最后一句话告诉我们,对于列表中的每个类型限定符(即 const
),ident 是一个如此限定的指针。所以它说 foo
是一个 const
指针。
但事实并非如此;我们通常将 int * const * foo
解释为将 foo
声明为非 const
指向 const
指向 int
.
的指针
这是标准中的错误还是对最后一句话有另一种解释?
T为int
,D为* foo
,“T D”不给出ident类型T,但是指向T的指针。
第二部分if
:
If ... and the type specified for ident in the declaration “T D” is
“derived-declarator-type-list T”
似乎可以确保 嵌套 是正确的。
如果有两颗星,则在到达直接声明符之前必须使用 D2 - D1 - D。
第二个例子:
typedef int *int_ptr;
const int_ptr foo;
显示它有多么棘手; const
远离 ident,但指针仍然是常量,而不是数据。
规范称之为澄清 - 现在 是一个错误。
有趣的是,在下一节“6.7.6.2 数组声明符”中,在相应的语义定义之后有一个 脚注:
When several "array of" specifications are adjacent, a
multidimensional array is declared.
几个相邻的“pointer of”规范的情况就不说了。有点“错误”。
1988 年的“参考手册”将 D1 和 D 调换了(!),但除此之外的措辞几乎完全相同。 (有 type-modifier 而不是 derived-declarator-type-list)。
例子类似:主要例子是int *ap[]
:
Here ap[] plays the role of D1; a declaration "int ap[]" would ...
与 int **pp
一起,*pp
扮演那个角色。
作为记录,有三个答案被其作者删除,支持 C 标准的这方面很棘手的结论。我不相信其他当前答案正确地将示例源文本 (int * const * foo
) 与标准段落中的符号 (T, D1、类型限定符列表,等等)。
因此我断定这确实是标准中的一个错误。
我认为解决方法就是删除最后一句话,“对于列表中的每个类型限定符,ident 是一个如此限定的指针。” type-qualifier 列表中的任何限定词已正确并入前一句,并且 D 中的任何限定词已并入该声明符.所以这似乎只是一个多余的句子,可能是在某些编辑中无意中出现的。
这是使标准正确的另一种解释。
为了
int * const * foo
形式
* type-qualifier-listopt D
说明你例子中的 D 是 * foo
所以我认为 indent 应该被替换为 * foo
而不是 foo
所以标准说 * foo
是一个 const
指针。
这意味着 foo
是指向 const
指针的指针。
C 2018 6.7.6.1 1 说:
If, in the declaration “T D1”, D1 has the form
* type-qualifier-listopt D
and the type specified for ident in the declaration “T D” is “derived-declarator-type-list T”, then the type specified for ident is “derived-declarator-type-list type-qualifier-list pointer to T”. For each type qualifier in the list, ident is a so-qualified pointer.
这道题是关于最后一句话的,但我们先完成第一句。
考虑声明 int * const * foo
。这里T是int
,D1是* const * foo
,type-qualifier-list 是 const
,D 是 * foo
.
那么T D是int * foo
,并且为ident指定“指向int
的指针”foo
,所以 derived-declarator-type-list 是“指针”。 (标准中没有对 derived-declarator-type-list 的公开解释,但是 6.7.8 3,讨论 typedef
,说它“由声明符指定D.”)
将这些代入第一句的最后一个子句告诉我们 T D1 指定 foo
的类型是“指向 const
的指针int
”。目前还好。
但是最后一句话告诉我们,对于列表中的每个类型限定符(即 const
),ident 是一个如此限定的指针。所以它说 foo
是一个 const
指针。
但事实并非如此;我们通常将 int * const * foo
解释为将 foo
声明为非 const
指向 const
指向 int
.
这是标准中的错误还是对最后一句话有另一种解释?
T为int
,D为* foo
,“T D”不给出ident类型T,但是指向T的指针。
第二部分if
:
If ... and the type specified for ident in the declaration “T D” is “derived-declarator-type-list T”
似乎可以确保 嵌套 是正确的。
如果有两颗星,则在到达直接声明符之前必须使用 D2 - D1 - D。
第二个例子:
typedef int *int_ptr;
const int_ptr foo;
显示它有多么棘手; const
远离 ident,但指针仍然是常量,而不是数据。
规范称之为澄清 - 现在 是一个错误。
有趣的是,在下一节“6.7.6.2 数组声明符”中,在相应的语义定义之后有一个 脚注:
When several "array of" specifications are adjacent, a multidimensional array is declared.
几个相邻的“pointer of”规范的情况就不说了。有点“错误”。
1988 年的“参考手册”将 D1 和 D 调换了(!),但除此之外的措辞几乎完全相同。 (有 type-modifier 而不是 derived-declarator-type-list)。
例子类似:主要例子是int *ap[]
:
Here ap[] plays the role of D1; a declaration "int ap[]" would ...
与 int **pp
一起,*pp
扮演那个角色。
作为记录,有三个答案被其作者删除,支持 C 标准的这方面很棘手的结论。我不相信其他当前答案正确地将示例源文本 (int * const * foo
) 与标准段落中的符号 (T, D1、类型限定符列表,等等)。
因此我断定这确实是标准中的一个错误。
我认为解决方法就是删除最后一句话,“对于列表中的每个类型限定符,ident 是一个如此限定的指针。” type-qualifier 列表中的任何限定词已正确并入前一句,并且 D 中的任何限定词已并入该声明符.所以这似乎只是一个多余的句子,可能是在某些编辑中无意中出现的。
这是使标准正确的另一种解释。
为了
int * const * foo
形式
* type-qualifier-listopt D
说明你例子中的 D 是 * foo
所以我认为 indent 应该被替换为 * foo
而不是 foo
所以标准说 * foo
是一个 const
指针。
这意味着 foo
是指向 const
指针的指针。