c++ 如何在声明中不能有多个decl-specifier-seq?

以下是无效代码:

int i = 0, double j = 2.0;

标准草案说明为什么:

[N4140/7.1.6]

2 As a general rule, at most one type-specifier is allowed in the
complete decl-specifier-seq of a declaration or in a
type-specifier-seq or trailing-type-specifier-seq. The only exceptions to this rule are the following:

const can be combined with any type specifier except itself.

volatile can be combined with any type specifier except itself.

signed or unsigned can be combined with char, long, short,
or int.

short or long can be combined with int.

long can be combined with double.

long can be combined with long.

是的,它阻止像int int这样的傻事,但是我看不到上面发送的无效代码有什么问题.引用[N4140 / 7],一个简单的声明包含一个decl-specifier-seqopt init-declarator-listopt;

[N4140 / 8]然后显示一个init-declarator-list由init-declarator-list,init-declarator,

init-declarator是一个声明器initializeropt.

由于我们只关心int i = 0形式的语法,所以我们关心的声明器是一个ptr-declarator,它是一个noptr-declarator,它是一个declarator-id属性-specifier-seqopt,最后是一个声明符-id仅由… opt id-expression组成.

为了完整,[N4140 / 5.1.1]表示一个id-expression可以是一个不合格的id或一个标识符.

如果我到目前为止还没有跳起来,这就是语法反映的.

int decl-specifier-seq

我不合格身份

= 0初始化器

int i = 0 init-declarator

由于简单声明具有decl-specifier-seq,因此只有一个decl-specifier-seq适用于整个init-declator-list.

有趣的是,这意味着你不能这样做:

int i, const j;

然而:

int i, * j;

是完全合法的,因为明星是ptr运算符的一部分.但你不能这样做:

int i, const * j; // pointer to const int

这意味着在下面的代码中,我成为一个指向const int的指针.惊喜!

int h = 25;
int const * j, * i = &h;
*i = 50; // error: assignment of read-only location '* i'

意图在[N4140 / 8]中明确:

3 Each init-declarator in a declaration is analyzed separately as
if it was in a declaration by itself.99

99) A declaration with several declarators is usually equivalent to
the corresponding sequence of declarations each with a single
declarator. That is

06005

is usually equivalent to

06006

问题是为什么会这样呢?

如果它是合法的,你可以在for循环中执行,这有点有用.

最佳答案
简短的答案:一个语句只允许“一个类型的声明”,但是这个声明可以声明“多个标识符”. const / volatile也是类型限定符或指针限定符,因此它们需要一个类型或指向绑定的指针.

长答案:

我从来没有读过这个标准,但是我去了

“它阻止像int int这样的东西,但是我上面发现的无效代码没有看到任何错误.”

>我看到的方式是,一个语句可以允许您只有一个声明,但一个声明可以允许您声明相同类型的多个标识符.
>所以int i = 0,double j = 2.0的问题;你有两种类型,即int和double.哪个违反[N4140 / 7.1.6].
>这是语言允许的,因此上述语句是不正确的.

但是,你进一步挖掘更深入,我相信你的混乱从此开始“因为我们只关心形式的语法…”.声明不会分解如下?

int i = 0 ::= simple-declaration
Where in...
int ::= type-specifier
i ::= identifier
= 0 ::= init-declarator

更多

你提到…

Not Allowed: int i, const j;
Allowed: int i, * j;
Not Allowed: int i, const * j; // pointer to const int
Allowed: int const * j, * i = &h;

我的回应:

Not Allowed: int i, const j; - because const is a type modifier, syntactically there is no type specified to bind to.
Allowed: int i, * j; - because * grabs the type int and j has a complete type.
Not Allowed: int i, const * j; - because const is not associated to a type here. It is the same problem as in the first case. Read it as j is a pointer to <unexpected word in between> and thus screws up the grammar.
Allowed: int const * j, * i = &h; - because syntactically const has a type to bind to.

“问题是为什么会这样呢?”

>当我学习C时,我最初在类型名称之前/之后使用const混淆,并清除混淆,我尝试了一些测试代码,并找出语言允许的内容,以下是我想出的内容.这是从我的旧笔记.它绝对看起来像是一个新程序员所做的东西.但是,它清除了大部分的疑虑.

[storage class] [sign qualifier] [size qualifier] [type qualifiers]< [* [type qualifiers]] [symbol name] [[] | ([参数])]> 存储类:auto,register,static,extern,typedef 签名限定符:signed,unsigned 大小限定词:短,长,长 基本类型:char,int,float,double,void 类型限定符:const,volatile 符号名称可以是变量,常量,类型(def)名称和函数 符号前缀*将其作为指针. *可以出现N次,使其成为指针到指针等等. A []后缀符号使其成为一个数组. []可以出现N次,使其成为多维数组. 符号后缀A()使其成为一个函数. ()可以出现N次,但是由于函数不能返回一个函数,当函数返回一个函数指针时,()可以再次出现.
上述帮助我在声明变量时直觉.

修改我年龄老笔记中的类型说明符语法:

[storage class] [sign qualifier] [size qualifier] <type> [type qualifiers] [* [pointer qualifiers]] [symbol name] [[] | ([parameters])]

这是const和volatile是类型限定符或指针限定符,它们需要一个类型或指向绑定的指针来限定它们.

考虑“一个语句可以允许您只有一个声明,但一个声明可以允许您声明相同类型的多个标识符”的想法.这意味着类型说明符的语法可以分解如下:

type ::= [storage class] [sign qualifier] [size qualifier] <type> [type qualifiers]

symbol ::= [* [pointer qualifiers]] [symbol name] [[] | ([parameters])]

并且声明的简化语法将是:

键入符号[,符号…]

显然,

int i,const j; – 不符合语法.

int const i,j; – 同意语法.

我相信一个人的标准可以使用标准,并提供答案使用正确的术语和参考.但是,请记住,经验不足的程序员可能会发现一个较不技术的答案很容易理解.

如果形式“int i,const j”被允许,那么可以写“int const i,const j”,这意味着j是双常量.这没有任何意义.

转载注明原文:c++ 如何在声明中不能有多个decl-specifier-seq? - 代码日志