【问题标题】:typedef struct but keep new type namespaced under keyword 'struct'typedef struct,但在关键字“struct”下保留新类型的命名空间
【发布时间】:2020-11-13 14:18:04
【问题描述】:

我怎样才能 typedef 一个结构,但仍保持新类型命名空间在关键字 'struct' 下?

示例:

struct foo {
    int x; 
}; 

typedef struct foo struct bar; 


int main(void) {
    struct bar bar; 
    bar.x = 10; 

    return 0; 
}

但这显然不起作用。 如果有人好奇,这里是错误:

main.c:5:20: error: two or more data types in declaration specifiers
 typedef struct foo struct bar;
                    ^
main.c:5:27: warning: useless storage class specifier in empty declaration
 typedef struct foo struct bar;
                           ^
main.c: In function 'main':
main.c:9:13: error: storage size of 'bar' isn't known
  struct bar bar;

【问题讨论】:

  • 你到底想让 typedef 做什么?只需将其删除。如果您删除 typedef 行,此代码将正常工作。
  • 如果你还想使用struct,那就不要typedef。
  • #define foo bar
  • 或者换句话说,为什么不直接使用struct foo 而不是struct bar?你想通过调用 bar 而不是 foo 来实现什么?
  • @topoly 对,所以typedef 显然不适合你。唯一的其他选择是#define,您也拒绝了它。因此,您的问题的答案很简单,“不,您不能那样做。”

标签: c struct typedef


【解决方案1】:

我找到了适用于 cygwin 的解决方案:

struct foo {
    int x; 
}; 

struct bar {
    struct foo; 
};

【讨论】:

  • 但那是无效的 C 语法,并没有给出你想要的。编译器将对此进行诊断。你不能使用struct bar y; y.x = 5; - 那是不可能的。发帖前没检查吗?
  • @RobertSsupportsMonicaCellio 是的,我做到了,而且成功了。
  • 如何编译?当我尝试使用 GCC 和 Clang 时,这是不可能的,因为 struct foo; 没有声明任何内容。 godbolt.org/z/nqz8aG
  • @RobertSsupportsMonicaCellio 我用 cygwin gcc 编译。我想这只是一个非标准的扩展。我会在 5 分钟内删除这个答案。
  • 您不需要删除它,但可以详细说明它在 Cygwin 中的工作原理。这似乎很有趣。
【解决方案2】:

我怎样才能 typedef 一个结构,但仍然保留新类型 命名空间 在关键字'struct'下?.

你不能。命名空间是一个声明性区域,它为其中的标识符(类型、函数、变量等的名称)提供范围。 C++ 中定义的命名空间概念并非 C 所固有的。

所以,如果你对你的需求的微小变化感到满意,而不是做一些不自然的事情,使用简单的 typedef:

而不是这个:

struct foo {
    int x; 
};  

这样做:

typedef struct {
    int x; 
}foo;  

那么这将起作用:

typedef foo bar;

int main(void )
{   
    bar b;  
  
    b.x = 10;
    return 0;  
}

注意:虽然 namespaces 不是 C 中固有的,但它们在 C++ 中是固有的,但有一些解释,例如:as discussed here,这证明了这一点。

【讨论】:

  • 您断言使用_t 是惯用的,这是值得怀疑的。您在明显支持中链接的编码指南确实在一个示例中使用了该约定,但它们只是众多指南中的一组指南,并且在任何情况下它们都没有将_t 约定用作其实际指南之一。另一方面,POSIX 保留以_t 结尾的标识符,这是避免在您自己的代码中使用此类标识符的一个很好的理由。
  • @JohnBollinger - 我很乐意用 common 来淡化 idiomatic 这个词。或者你会在这里推荐一种不同的方法吗?
  • @JohnBollinger - 在阅读了您评论的 rest 之后,我同意。它确实与POSIX 冲突,因此编辑了整个_t。谢谢。
  • @rykker ... 尽管如此,我工作过的每家公司的编码规则(嵌入式软件)都指定了_t 规则(_s 用于typedefs 之前的结构和_e 用于枚举)。我赞成这个意图(虽然没有直接回答一个有点超现实的问题)。
  • @RobertoCaboni - 谢谢。我以前遇到过这个。在这个网站上,我必须记住,有些开发人员确实需要在社区内遵守这样的规则,而且是有充分理由的。当软性建议足够时,我只需要避免做出硬性断言。 :)
【解决方案3】:

你不能。这不是它的工作原理。

您不能“创建”名称超过一个单词的类型,也不能使用关键字 struct 引用类型别名。

在这种情况下,编写struct 的目的是通过未作为别名引入的名称来引用结构类型。那里的关键字是说这就是你想要做的。但这不是名称的一部分;它不能是名称的一部分。

幸运的是,没有理由需要甚至想要这个。

【讨论】:

  • @EricPostpischil 我不相信我另有主张?我会尽量让句子更清楚。
  • 如果有两个库使用具有相同布局但不同标签的结构,并且希望能够让它们对相同的数据进行操作,那么有一种标准的方式来告诉编译器将这两个结构标记视为同义词。不幸的是,编写可以接受指向具有兼容布局的任意结构类型的指针的函数的能力是 1974 年支持的一项功能,此后一直被广泛使用,但标准尚未承认这一点。
  • @supercat 这似乎与这个问题或这个答案没有任何关系。
  • @AsteroidsWithWings 他建议用另一种方法来实现 OP 想要的。
  • @dbush 我没有看到任何建议,只有历史课,但没关系 - 他可以在问题下的 cmets 或使用 @topoly...或者写一个答案。别名不同但布局兼容的类型与此答案无关。
【解决方案4】:

我怎样才能typedef 一个结构,但仍将新类型命名空间保留在关键字“结构”下?

所以,您似乎想为另一种结构类型定义结构别名。

typedef 无法做到这一点,因为它会创建一个单词别名。新别名不能由多个空格分隔的单词组成。

但是您可以使用像 struct_bar 这样的单个名称,并在名称内部实现 struct 以表明 bar 是一个结构。

#include <stdio.h>

struct foo {
    int x; 
}; 

typedef struct foo struct_bar;


int main(void) {
    struct_bar bar;
    bar.x = 10; 

    return 0; 
}

【讨论】:

    【解决方案5】:

    C 对命名空间没有任何类型的支持(至少在 C++ 的意义上没有)。

    当您创建typedef 时,新类型名称是单个标识符,而不是多个单词。所以struct bar 不能是其他类型的别名。您必须将其命名为 bar 或其他单字名称。

    【讨论】:

    • 我敢肯定 topoly 没有使用 C++ 意义上的“命名空间”,而是更一般的英语(实际上是软件开发)意义上的。
    • @AsteroidsWithWings - dbush 在 C 意义上使用它。 C 中有四个命名空间,标准中提到了(好吧,无论如何都是“命名空间”)。
    • @StoryTeller-UnslanderMonica 显然不是,因为他们说 C 没有那个。
    • @AsteroidsWithWings - 它不会改变这个答案。您只能真正操纵其中一个名称空间。
    • @StoryTeller-UnslanderMonica 我不确定你为什么要告诉我这个。 :) dbush “更正” OP 谈论命名空间,因为 C 不支持它们;我指出 OP 指的是别的东西。而已。就是这样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2010-12-13
    相关资源
    最近更新 更多