【问题标题】:How is this typedef possible? [duplicate]这个 typedef 怎么可能? [复制]
【发布时间】:2016-05-01 20:10:57
【问题描述】:

在this SO question我遇到了一个非常奇怪的typedef:

struct Date {
    int day, month, year;
} typedef date_s;

我一直看到typedefs 遵循这条“规则”:

typedef <existing> <new>;

例如:

typedef unsigned long long ull;
typedef int kph; // speed
typedef void (*alpm_cb_log)(alpm_loglevel_t, const char *, va_list);

typedef int int_t;
typedef char char_t, *char_p, (*fp)(void);

第4个取自here,第5个和第6个取自cppreference


而this 就是我的typedef struct:

typedef struct {
    int a, b, c;
} data;

// and then use it
data Something;

问题是这怎么可能写出这样的typedef?这甚至没有意义(至少对我来说)。

clang 不会给出任何错误或警告,即使是 -Wall -Wextra。

额外问题:我是否应该建议问题的作者在哪里可以找到此代码避免使用这样的typedef(因为它非常不寻常并且可能导致混乱)?

【问题讨论】:

  • 这很好,虽然不寻常。很像 int const i;
  • @piling 我更喜欢int const i,而不是const int i。使用指针时不那么令人困惑,因为您只需要遵循一个一般规则:“const 之前的任何内容都是 const”。 int const* i; 比 const int *i; 简洁得多。
  • 实际规则是它与声明变量相同,但将typedef(几乎)放在任何地方都会使其声明类型别名而不是变量。为了清楚起见,人们通常把它放在前面

标签: c typedef


【解决方案1】:

原来typedef 可以放在现有类型之后(除了它之前)。这个小奇怪,现在已经过时*,是由 C 标准“捆绑”typedefs 与 存储类说明符的方式引起的,例如 static 和auto:

声明定义如下:

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}*

这意味着声明说明符可以以任何顺序出现。现在,声明说明符是

<declaration-specifier> ::= <storage-class-specifier>
                          | <type-specifier>
                          | <type-qualifier>

而存储类说明符是

<storage-class-specifier> ::= auto
                        | register
                        | static
                        | extern
                        | typedef

struct 元素的声明是一个类型说明符。像typedef 关键字一样,它是一个声明说明符。由于声明说明符可以按任何顺序出现,typedef 的两个位置(即struct 之前和之后)都是有效的并且彼此相同。

*N1570, 6.11.5:“存储类说明符在声明中的声明说明符开头以外的位置是一个过时的功能。”谢谢Keith Thompson,您的评论很棒!

【讨论】:

  • N1570 6.11.5:“存储类说明符在声明中的声明说明符开头以外的位置已过时。”它仍然是完全合法的,但该语言的未来版本可能会使其非法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
  • 2019-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多