Con*_*tor 70 c++ gcc g++ c++11
以下代码使用g ++ 4.8.1成功编译:
int main()
{
int(*)();
}
Run Code Online (Sandbox Code Playgroud)
它看起来像一个函数指针的简单声明:
int(*f)();
Run Code Online (Sandbox Code Playgroud)
它不能用clang 3.4和vc ++ 2013编译.
它是编译器错误还是标准的黑暗之处?
int(*)();
int(*);
int(*){};
int(*());
更新1: @Ali在评论中添加了一些有趣的信息:
所有4个案例都使用clang 3.5 trunk(202594)进行编译错误,并使用gcc 4.9 trunk(20140302)进行编译.行为是一样的
-std=c++98 -pedantic
,除了int(*){};
可以理解的; 扩展初始化程序列表仅适用于-std=c++11
.
更新2:正如@CantChooseUsernames在他的回答中指出的那样,即使没有任何启用的优化,即使初始化它们仍然可以正常编译并且没有为它们生成汇编(无论是否初始化):
int(*)() = 0;
int(*) = 0;
int(*){} = 0;
int(*()) = 0;
更新3:我真的很惊讶地发现int(*)() = "Hello, world!";
编译也很好(int(*p)() = "Hello, world!";
当然不会编译).
更新4:太棒了但int(*){} = Hello, world!;
编译得很好.而下面的怪异之极的一段代码,也:int(*){}() = -+*/%&|^~.,:!?$()[]{};
(活生生的例子).
这和许多相关的句法问题被跟踪为gcc bug 68265.
Vla*_*cow 15
根据C++标准(第7节声明中的第6页)
6 init-declarator-list 中的每个init-declarator只包含一个declarator-id,它是init-declarator声明的名称,因此声明声明了一个名称
所以它只是一个编译器错误.
有效的代码可能看起来像(除了你显示的函数指针声明),虽然我不能用我的MS VC++ 2010编译它.
int(*p){};
Run Code Online (Sandbox Code Playgroud)
您用于测试的编译器似乎允许声明而没有declarator-id.
还要考虑8.1节类型名称的以下段落
1要显式指定类型转换,并作为sizeof,alignof,new或typeid的参数, 应指定类型的名称.这可以使用type-id来完成,它在语法上是对该类型的变量或函数的声明,省略了实体的名称.
我不确定这有多大帮助,但我尝试了以下(clang 3.3,g ++ 4.8.1):
using P = int(*)();
using Q = int*;
P; // warning only
Q; // warning only
int(*)(); // error (but only in clang)
int*; // error
int(*p)(); // ok
int *q; // ok
Run Code Online (Sandbox Code Playgroud)
另一方面,g ++ 4.8.2和4.9.0中的所有内容都很好.不幸的是,我没有铿锵声3.4.
非常粗略地,声明[iso section 7]按顺序包含以下部分:
static
,virtual
)const double
,vector<int>
)n
,*p
,a[7]
,f(int)
)const
,noexcept
)= {1,2,3}
或{ return 0; }
现在,说明符大致由名称和任选的一些说明符操作符[异8/4].
前缀运算符,例如:
*
(指针)*const
(常量指针)&
(左值参考)&&
(右值参考)auto
(函数返回类型,尾随时)后缀运算符,例如:
[]
(阵列)()
(功能)->
(函数尾随返回类型)上述运算符旨在反映它们在表达式中的用法.Postfix运算符绑定比前缀更紧密,括号可用于更改它们的顺序:int *f()
是一个返回指针的函数int
,而是int (*f)()
一个返回函数的指针int
.
也许我错了,但我认为这些运营商不能在声明中没有名字.因此,当我们编写时int *q;
,则int
是基类型,并且*q
是由前缀运算符*
后跟名称组成的声明符q
.但int *;
不能单独出现.
另一方面,当我们定义时using Q = int*;
,声明Q;
本身就很好,因为Q
它是基类型.当然,因为我们没有声明任何内容,我们可能会根据编译器选项获得错误或警告,但这是一个不同的错误.
以上只是我的理解.标准(例如N3337)所说的是[iso 8.3/1]:
每个声明符只包含一个declarator-id ; 它命名声明的标识符.声明器id中出现的unqualified-id应该是一个简单的标识符,除了声明一些特殊函数(12.3 [ 用户定义的转换 ],12.4 [析构函数],13.5 [重载运算符])和模板特化声明或部分专业化(14.7).
(方括号中的注释是我的).所以我理解int(*)();
应该是无效的,我不能说为什么它在clang和不同版本的g ++中有不同的行为.
你可以使用这个:http://gcc.godbolt.org/来查看程序集..
int main()
{
int(*)() = 0;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
产生:
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
Run Code Online (Sandbox Code Playgroud)
这相当于: int main() {return 0;}
所以即使没有优化,gcc也不会为它生成汇编.它应该发出警告或错误吗?我没有任何线索,但它不关心或做任何未命名的func指针.
然而:
int main()
{
int (*p)() = 0;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
没有优化会产生:
main:
pushq %rbp
movq %rsp, %rbp
movq $0, -8(%rbp)
movl $0, %eax
popq %rbp
ret
Run Code Online (Sandbox Code Playgroud)
在堆栈上分配8个字节..
归档时间: |
|
查看次数: |
3858 次 |
最近记录: |