void 究竟是什么意思?它如何以这种奇怪的方式使用?

What does void actually mean? How is it usable in this weird way?

我听说过很多关于这行的事:void typedef name

编译良好:

void typedef name;
int main(){}

void 到底是什么意思?这不就意味着某些东西只是空的吗?如何在typedef这样的关键字前使用? void不是无效使用吗?好像和做的一样:

typedef void name;

并使 name 成为 void 的别名。 编译器是否重新排列 typedefvoid

我以为 void 只能用于函数:

void func();

但是void可以用于什么东西,这意味着什么?即使 void typedef name 不是函数声明,它又是如何工作的?

typedef在语法上是一个存储class说明符,其中在声明说明符中只能有一个(_Thread_local除外).

声明符的顺序(“T”,而不是声明的“D”部分)是自由的——大多数是 const char 而不是 char const。但是例如char const*const x也用

在语义上,typedef 为给定类型创建“仅”同义词。所以是的,编译器确实重新排列(解析该声明)

虽然 void x; 声明会出错,但它会使用 typedef 进行编译。取决于你以后如何使用它,例如对于指针:

   typedef void _0;
    _0 *y;  

虽然_0* y是一样的,但是*的位置是不能调换的。它位于声明符(“D”)的左侧,给出 T*D 和所有白色-space 变体。

在 C 语言中,声明 是一个或多个 声明说明符,后跟一列 声明符 和可选的 初始化器 。人们倾向于以特定顺序编写说明符,但 C 语法允许以任何顺序编写它们。他们是:

  • 存储-class-说明符: typedef, extern, static, _Thread_local, autoregister.
  • 类型说明符: void, char, short, int, long, float, double, signed, unsigned, _Bool, _Complex, _Atomic (<i>type-name </i>),以及结构说明符、联合说明符、枚举说明符和(先前定义的)typedef 名称。
  • 类型限定符constrestrictvolatile_Atomic
  • 函数说明符inline_Noreturn.
  • 对齐说明符: _Alignas (<i>type-name</i>) and _Alignas (<i>常量表达式</i>).

对于各种说明符可以出现多少次以及哪些可以与哪些一起出现有一些规则。但是,对于它们出现的顺序没有规定。因此,以上所有内容都可以根据需要重新排列。这包括将一些说明符放在我们通常组合在一起的 类型说明符 之间,例如 const long static int _Alignas (double) long signed x;,它以令人困惑的方式包含 signed long long int。编译器不关心;它会记住一切并计算出来。

所以void typedef <i>name</i>typedef void <i>name[=112=是一样的];它将 <i>name</i> 定义为 void.

的别名

从上面的列表中可以看出,void 是一个 类型说明符 。很简单,它指定了一个类型。该类型被定义为 incomplete,这意味着它没有定义大小。此外,C 标准指定它不能完成;不能给它尺寸。它没有大小的事实可以防止程序意外地引用 void 对象:如果 p 是一个 void *,那么 *p 将引用一个 void ] 对象,并且,如果程序实际尝试访问它,编译器应该发出诊断消息。

补充说明

声明中的声明符是围绕声明的标识符构建的东西:

  • 一个普通的标识符
  • 一个声明符跟在括号[]之后表示一个数组,括号内有各种选项。
  • 一个声明符后跟括号()表示一个函数,括号内有各种选项。
  • 一个 声明符 前面有 * 来表示一个指针,可选地带有 类型限定符(如 const) 在 * 和声明符之间。
  • 一个 declarator 在括号内,以覆盖复杂的 declarators 混合指针和数组等的默认分组。