GCC 允许 1 行声明多个指针,但不是非指针,具有不同的 const 限定符
GCC allows 1-line declaring of multiple pointers, but not non-pointers, with different const qualifiers
鉴于以下程序,GCC(g++
,但我假设非std::
位也适用于 C),as can be seen on IDEone.com, 行为如下:
- 它允许在一行中声明多个指针,每个指针都有自己可能不同的
const
限定条件,这很荣幸。
- 它不允许多个非指针相同。相反,第一个变量的
const
或缺少第一个变量用于该行中声明的所有变量。任何其他 const
关键字都会产生语法错误。
因此我的问题是:
- 在指针和非指针情况下,这是预期的正确行为吗?
- 为什么在标准化语法方面存在这种差异?
我已经搜索过了,但没有成功。我面前确实有 n3797.pdf 打开,但我似乎还没有达到理解其语法规范的要求水平。 :( 所以希望有人可以根据需要进行评估和翻译。
请不要只说不要在一行中声明多个变量。我知道为什么不鼓励这样做,但我尽量不这样做。 FWIW,for
循环使它成为获得 const
结束迭代器的一种方式很诱人——如果所述迭代器是指针,这似乎是可能的,但如果它是 class,则不是。无论如何,我不要求代码审查。主题是为什么存在这种差异,与利用它的建议程度无关。
#include <iostream>
#include <type_traits>
int main()
{
int i{42};
int *p1 = &i, *const p2 = &i; // OK
std::cout << std::is_const< decltype(p1) >::value << '\n'; // 0
std::cout << std::is_const< decltype(p2) >::value << '\n'; // 1
int *const p3 = &i, *p4 = &i; // OK
std::cout << std::is_const< decltype(p3) >::value << '\n'; // 1
std::cout << std::is_const< decltype(p4) >::value << '\n'; // 0
int const l = i, m = i; // OK
std::cout << std::is_const< decltype(l) >::value << '\n'; // 1
std::cout << std::is_const< decltype(m) >::value << '\n'; // 1
//int j = i, const k = i; // error: expected unqualified-id before ‘const’
}
正如@JonathanLeffler 指出的那样:
Chapter 8 of n3797.pdf (p180-181) shows that this is OK in the grammar rules there.
声明符列表的每个元素可以是 noptr-声明符 或 ptr-声明符。 ptr-operator ptr-declarator 案例的组件有自己的 cv-qualifier-seq opt .但是 noptr-declarator 没有。
法律术语说了这么多,但为什么会这样呢?好吧,一旦我开始更多地考虑这个问题,它就有意义了:前导类型名和声明符列表之间存在明显的区别。非指针声明符创建具有该确切类型的变量,因此具有与它相同的 const
ness。
相比之下,指针声明符也有自己的 const
ness,与所引用的类型不同。而且我认为声明符列表中的每个指针都可以具有不同的 const
ness 的原因是由于 ptr-operator 绑定的((in)famous)方式:到变量名称,而不是引用的变量类型。
所以像这样的代码被视为 'equivalent' 非指针声明并且意味着 'all of these pointers are themselves const'...
int* const p = &i, q = &j, r = &l;
...那么语法必须完全不同,并且将 ptr-operator 视为类型名的一部分,而不是每个变量的属性。
但正如我们所知,后者才是正确的。因此,鉴于此,每个 ptr-operator 组件中 cv-qualifier-seq opt 的存在是让 one 指针有自己的 const
ness,与所指类型的不同。事实上,声明符列表中的每个其他指针都可以具有不同的 const
ness 只是其副作用,因为每个声明符都需要自己的 ptr-operator(以避免成为非指针)。
事后看来,这一切似乎都很明显。我想我今天过得很慢。
鉴于以下程序,GCC(g++
,但我假设非std::
位也适用于 C),as can be seen on IDEone.com, 行为如下:
- 它允许在一行中声明多个指针,每个指针都有自己可能不同的
const
限定条件,这很荣幸。 - 它不允许多个非指针相同。相反,第一个变量的
const
或缺少第一个变量用于该行中声明的所有变量。任何其他const
关键字都会产生语法错误。
因此我的问题是:
- 在指针和非指针情况下,这是预期的正确行为吗?
- 为什么在标准化语法方面存在这种差异?
我已经搜索过了,但没有成功。我面前确实有 n3797.pdf 打开,但我似乎还没有达到理解其语法规范的要求水平。 :( 所以希望有人可以根据需要进行评估和翻译。
请不要只说不要在一行中声明多个变量。我知道为什么不鼓励这样做,但我尽量不这样做。 FWIW,for
循环使它成为获得 const
结束迭代器的一种方式很诱人——如果所述迭代器是指针,这似乎是可能的,但如果它是 class,则不是。无论如何,我不要求代码审查。主题是为什么存在这种差异,与利用它的建议程度无关。
#include <iostream>
#include <type_traits>
int main()
{
int i{42};
int *p1 = &i, *const p2 = &i; // OK
std::cout << std::is_const< decltype(p1) >::value << '\n'; // 0
std::cout << std::is_const< decltype(p2) >::value << '\n'; // 1
int *const p3 = &i, *p4 = &i; // OK
std::cout << std::is_const< decltype(p3) >::value << '\n'; // 1
std::cout << std::is_const< decltype(p4) >::value << '\n'; // 0
int const l = i, m = i; // OK
std::cout << std::is_const< decltype(l) >::value << '\n'; // 1
std::cout << std::is_const< decltype(m) >::value << '\n'; // 1
//int j = i, const k = i; // error: expected unqualified-id before ‘const’
}
正如@JonathanLeffler 指出的那样:
Chapter 8 of n3797.pdf (p180-181) shows that this is OK in the grammar rules there.
声明符列表的每个元素可以是 noptr-声明符 或 ptr-声明符。 ptr-operator ptr-declarator 案例的组件有自己的 cv-qualifier-seq opt .但是 noptr-declarator 没有。
法律术语说了这么多,但为什么会这样呢?好吧,一旦我开始更多地考虑这个问题,它就有意义了:前导类型名和声明符列表之间存在明显的区别。非指针声明符创建具有该确切类型的变量,因此具有与它相同的 const
ness。
相比之下,指针声明符也有自己的 const
ness,与所引用的类型不同。而且我认为声明符列表中的每个指针都可以具有不同的 const
ness 的原因是由于 ptr-operator 绑定的((in)famous)方式:到变量名称,而不是引用的变量类型。
所以像这样的代码被视为 'equivalent' 非指针声明并且意味着 'all of these pointers are themselves const'...
int* const p = &i, q = &j, r = &l;
...那么语法必须完全不同,并且将 ptr-operator 视为类型名的一部分,而不是每个变量的属性。
但正如我们所知,后者才是正确的。因此,鉴于此,每个 ptr-operator 组件中 cv-qualifier-seq opt 的存在是让 one 指针有自己的 const
ness,与所指类型的不同。事实上,声明符列表中的每个其他指针都可以具有不同的 const
ness 只是其副作用,因为每个声明符都需要自己的 ptr-operator(以避免成为非指针)。
事后看来,这一切似乎都很明显。我想我今天过得很慢。