- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
以下是无效代码:
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
orunsigned
can be combined withchar
,long
,short
, orint
.—
short
orlong
can be combined withint
.—
long
can be combined withdouble
.—
long
can be combined withlong
.
是的,它可以防止像 int int
这样的傻事,但我看不出上面发布的无效代码有什么问题。引用 [N4140/7]
,simple-declaration 由 decl-specifier-seqopt init-declarator-list<子>选择;
[N4140/8]
然后显示 init-declarator-list 由 init-declarator-list 、 初始化声明器,
并且一个 init-declarator 是一个 declarator 初始化器opt。
由于我们只关心 int i = 0
形式的语法,那么我们关心的 declarator 就是 ptr-declarator,这是一个noptr-declarator,这是一个declarator-id attribute-specifier-seqopt,最后是一个declarator- id 仅由 ...
opt id-expression 组成。
为了完整起见,[N4140/5.1.1]
表示 id-expression 可以是 unqualified-id,或者只是 < em>标识符。
如果我到目前为止还没有绊倒,这就是语法所反射(reflect)的。
int
decl-specifier-seq
i
unqualified-id
= 0
初始化器
int i = 0
init-declarator
由于simple-declaration有decl-specifier-seq,只有一个decl-specifier-seq适用于整个init-declarator-list。
有趣的是,这意味着你不能做这样的事情:
int i, const j;
还是:
int i, * j;
是完全合法的,因为星号是 ptr-operator 的一部分。但你不能这样做:
int i, const * j; // pointer to const int
这意味着在下面的代码中,i
变成了一个指向 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.9999) A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator. That is
T D1, D2, ... Dn;
is usually equivalent to
T D1; T D2; ... T Dn;
问题是为什么会这样?
如果合法,可以在 for 循环中进行,这有点用处。
最佳答案
简答:一个语句只能允许“一个类型的声明”,但该声明可以声明“多个标识符”。 const/volatile 也是类型限定符或指针限定符,因此它们需要绑定(bind)类型或指针。
长答案:
我从未阅读过标准,但我来了...
“它可以防止像 int int 这样愚蠢的事情,但我看不出上面发布的无效代码有什么问题。”
但是你继续深入挖掘,我相信你的困惑从这里开始“因为我们只关心形式的语法......”。声明不会分解如下吗?
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 感到困惑,为了消除混淆,我尝试了一些测试代码并弄清楚该语言允许什么,以下是我想出的和。它来 self 的旧笔记。它绝对看起来像是一个新程序员制作的东西。但是,它消除了大部分疑虑。
[存储类] [符号限定符] [大小限定符] [类型限定符] <[* [类型限定符]] [符号名称] [[] | ([参数])]>
存储类:auto、register、static、extern、typedef
符号限定符:有符号、无符号
大小限定符:short、long、long long
基本类型:char、int、float、double、void
类型限定符:const、volatile
符号名称可以是变量、常量、类型(定义)名称和函数
符号前面的 * 使它成为一个指针。 * 可以出现N次,使其成为指针对指针等等。
符号后缀的 [] 使其成为一个数组。 [] 可以出现 N 次,是一个多维数组。
符号后缀的 () 使其成为函数。 () 可以出现 N 次,但是由于函数不能返回函数,所以 () 可以在函数返回函数指针时再次出现。
上面的内容帮助我在声明变量时思考得更清楚。
从我古老的笔记中修改类型说明符语法:
[storage class] [sign qualifier] [size qualifier] <type> [type qualifiers] [* [pointer qualifiers]] [symbol name] [[] | ([parameters])]
也就是说 const 和 volatile 要么是类型限定符,要么是指针限定符,它们需要绑定(bind)类型或指针来限定它们。
考虑“一个语句只能允许您进行一个声明,但一个声明可以允许您声明多个相同类型的标识符”的想法。这意味着类型说明符语法可以分解如下:
type ::= [storage class] [sign qualifier] [size qualifier] <type> [type qualifiers]
symbol ::= [* [pointer qualifiers]] [symbol name] [[] | ([parameters])]
声明的简化语法是:
输入符号[,符号...]
很明显,
int i, 常量 j; - 不符合语法。
int 常量 i, j; - 符合语法。
我确信熟悉标准的人可以使用标准并使用正确的术语和引用资料提供答案。但是,请记住,经验不足的程序员可能会发现技术含量较低且易于理解的答案。
如果允许“int i, const j”的形式,那么可以写成“int const i, const j”,这意味着 j 是一个双常量。这没有任何意义。
关于c++ - 为什么不能在声明中包含多个 decl-specifier-seq?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27432506/
在 C++ 中,如果我写 a c , meaning 可以是表达式语句 (a c或 a 类型变量 c 的声明. 为什么这不是 java 中的问题?是 (a c被泛型废弃的选项,因为虽然它解析了,
constexpr 函数的标准 在 [decl.constexpr] 的第 5 点下声明: For a non-template, non-defaulted constexpr function o
以下是无效代码: int i = 0, double j = 2.0; 标准草案说明了原因: [N4140/7.1.6] 2 As a general rule, at most one type-s
我将完整的 C++ 语法复制到我的解析器生成器中,但在解析 C++ 声明时遇到问题。在解析像 char* varname 这样的指针类型声明时,我们应该如何解释 decl-specifier? 以MS
以下代码可以用 clang 编译。我想知道 C++ 标准是否适合这个。 class A { static void x; // #1 static const void x; // #2
考虑以下程序: extern class A; int main() {} 根据 C++ 标准,这是格式正确的吗?如果格式错误,是否需要诊断?对于不同的编译器,我得到不同的结果: Clang:没有编译
我在 def 声明中使用 Scalameta(v1.8.0) 注释: trait MyTrait { @MyDeclDef def f2(): Int } 定义的注释类只返回输入,如下所示:
我有一个围绕 win32/pthreads 的 C++ 线程包装器类。问题出在我的标题中,我需要很多重要的东西,例如 windows.h 和 boost::function,以便在下面声明我的 typ
我试图将所有 FunctionDecl 节点存储在一个 vector 中,以便我将来可以访问它们。用例将用于进入函数(例如,函数 a 调用函数 b,我希望能够在函数 b 节点上调用 VisitDecl
我目前正在使用 SWIG/jni 从 Android 应用程序的 java 调用 C++ 函数。但是,每当函数返回 jstring 时我都会遇到困难。应用程序启动时,我在 LogCat 中收到以下错误
我是c语言新手。因此,我从 Brian Kernighan 和 Dennis Ritchie 的书(《C 编程语言》)中复制了代码。我正在复制 pg32 示例。当我收到此错误时: pg32.c: In
我懂了 DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" se
我是一名优秀的程序员,十分优秀!