为什么海湾合作委员会允许类型为void(非指针)的外部声明? [英] Why does gcc allow extern declarations of type void (non-pointer)?

查看:131
本文介绍了为什么海湾合作委员会允许类型为void(非指针)的外部声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么海湾合作委员会允许void类型的外部声明?这是一个扩展或
标准C?是否有可以接受的用途呢?

我猜测它是一个扩展,但我不觉得它在提到:结果
<一href=\"http://gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/C-Extensions.html\">http://gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/C-Extensions.html

  $猫extern_void.c
EXTERN无效美孚; / * OK在GCC 4.3,而不是在Visual Studio 2008中确定* /
无效* get_foo_ptr(无效){返回&放大器; foo的; }$ GCC -c extern_void.c#没有编译错误$ GCC --version |头-N 1
海湾合作委员会(Debian的4.3.2-1.1)4.3.2

定义foo的类型为void当然是一个编译错误:

  $ GCC -c -Dextern = extern_void.c
extern_void.c:1:错误:'富'的存储大小是未知

为了便于比较,Visual Studio 2008中提供了有关外部声明的错误:

  $ CL / C extern_void.c
微软(R)32位C / C ++优化编译器版本为15.00.21022.08的80x86
版权所有(C)微软公司。版权所有。extern_void.c
extern_void.c(1):错误C2182:'富':非法使用类型为无效


解决方案

奇怪的是(或许不那么奇怪......),它看起来对我来说,GCC是正确接受这种说法。

如果这个被宣布静态而不是的extern 的话,那就有内部链接和§6.9.2 / 3将适用:


  

如果一个对象标识符的声明是一个暂定的定义,并具有内部
  联动,声明的类型不得不完全类型。


如果它没有指定任何存储类(的extern ,在这种情况下),然后§6.7/ 7将适用:


  

如果一个对象标识符与无连锁宣布,该对象的类型应在其声明的年底完成,或者通过其init声明符结束时,如果它有一个
  初始化;在函数参数(包括原型),它是经调整的类型(见6.7.5.3),该需要是完整的。这样


我这两种情况下,无效是行不通的,因为(§6.2.5/ 19):


  

void类型[...]是一个不完整的类型无法完成。


然而

的那些应用。这似乎只留下的§6.7.2/ 2的要求,这似乎让同类型的名称无效的声明:


  

至少有一个类型说明符应在每个声明的声明说明符给出,
  并在每个结构声明和类型名称说明符限定符列表。的每个列表
  类型说明符应为以下组之一(以逗号分隔,当有
  多线路上一组);可发生于任何订单的类型说明符,可能
  混合与其他声明说明符。


  
  

      
  • 无效

  •   
  • 字符

  •   
  • 符号字符

  •   

  
  

[...更多类型的省略]


我不知道这是真的有意的 - 我怀疑无效是真的打算搞什么派生类型(例如,指向void),或从返回类型一个功能,但我无法找到任何直接指定限制。

Why does gcc allow extern declarations of type void? Is this an extension or standard C? Are there acceptable uses for this?

I am guessing it is an extension, but I don't find it mentioned at:
http://gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/C-Extensions.html

$ cat extern_void.c
extern void foo; /* ok in gcc 4.3, not ok in Visual Studio 2008 */
void* get_foo_ptr(void) { return &foo; }

$ gcc -c extern_void.c # no compile error

$ gcc --version | head -n 1
gcc (Debian 4.3.2-1.1) 4.3.2

Defining foo as type void is of course a compile error:

$ gcc -c -Dextern= extern_void.c
extern_void.c:1: error: storage size of ‘foo’ isn’t known

For comparison, Visual Studio 2008 gives an error on the extern declaration:

$ cl /c extern_void.c 
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

extern_void.c
extern_void.c(1) : error C2182: 'foo' : illegal use of type 'void'

解决方案

Strangely enough (or perhaps not so strangely...) it looks to me like gcc is correct to accept this.

If this was declared static instead of extern, then it would have internal linkage, and §6.9.2/3 would apply:

If the declaration of an identifier for an object is a tentative definition and has internal linkage, the declared type shall not be an incomplete type.

If it didn't specify any storage class (extern, in this case), then §6.7/7 would apply:

If an identifier for an object is declared with no linkage, the type for the object shall be complete by the end of its declarator, or by the end of its init-declarator if it has an initializer; in the case of function arguments (including in prototypes), it is the adjusted type (see 6.7.5.3) that is required to be complete.

I either of these cases, void would not work, because (§6.2.5/19):

The void type [...] is an incomplete type that cannot be completed.

None of those applies, however. That seems to leave only the requirements of §6.7.2/2, which seems to allow a declaration of a name with type void:

At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each struct declaration and type name. Each list of type specifiers shall be one of the following sets (delimited by commas, when there is more than one set on a line); the type specifiers may occur in any order, possibly intermixed with the other declaration specifiers.

  • void
  • char
  • signed char

[ ... more types elided]

I'm not sure that's really intentional -- I suspect the void is really intended for things like derived types (e.g., pointer to void) or the return type from a function, but I can't find anything that directly specifies that restriction.

这篇关于为什么海湾合作委员会允许类型为void(非指针)的外部声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆