【问题标题】:How to assign a C struct inline?如何分配 C 结构内联?
【发布时间】:2011-06-14 05:22:24
【问题描述】:
typedef struct {
    int hour;
    int min;
    int sec;
} counter_t;

在代码中,我想在不显式初始化每个成员变量的情况下初始化这个结构的实例。也就是说,我想做这样的事情:

counter_t counter;
counter = {10,30,47}; //doesn't work

10:30:47

而不是

counter.hour = 10;
counter.min = 30;
counter.sec = 47;

不记得这个的语法,也没有立即从谷歌上找到一种方法。

谢谢!

【问题讨论】:

  • 是的,如果我像 counter_t counter = {10,30,47} 那样在同一行中进行声明,它看起来很有效,但如果声明在此分配之前完成,则不会。
  • @Oli:为什么会这样?正如所写,这是一项任务,而不是初始化。
  • @sth:问题好像被修改了……
  • 正如史蒂夫的回答中提到的,你所拥有的是 assignment 而不是 initialization (正如你在标题中所说)。 C 比 C++ 更模糊了这些界限,但正如 Oli 所指出的,初始化(在 C 和 C++ 中)已经按照您的预期工作。
  • @Oli @sth:是的,我想知道您是否在修改之前看到过它。在很短的一段时间内(大约一分钟),我得到了声明的工作版本,即counter_t counter = {10,30,47};。当我意识到它确实有效时,我改变了它:)。无论如何,我真正想要的是将它与赋值分开声明。 @Fred Nurk:好电话,我将标题更改为“分配”。谢谢!

标签: c++ c struct


【解决方案1】:

初始化:

counter_t c = {10, 30, 47};

作业:

c = (counter_t){10, 30, 48};

后者被称为“复合文字”。

【讨论】:

  • 请注意,这需要 GCC 或 C99,而不是严格的 C89 或 C++ 编译器。
  • @Jeremiah:好点,我没有注意到 C++ 标签。至于 C89,如果人们在说“C89”时到处说“C”,就我而言,他们是靠自己的 ;-)
  • @RBerteig:毫无疑问。我并不是说没有人应该使用 C89,我是说如果他们不能使用 C99,那么他们不应该只是说他们正在使用的是“C”,而没有进一步的警告。
  • @RBerteig:好吧,考虑到我厌倦了 C89 和 C99 是同一种语言的普遍看法。应该是 C89 农奴必须添加额外的资格 ;-) 我这么说是作为最近在 2008 年自己编写纯 C89 代码的人。
  • @Fred:那么容易吗?例如,如果平台至少不提供alloca,那么您的C99 编译器必须动态分配VLA,这很麻烦。一旦你不能很好地使用目标的堆栈,setjmp 的实现可能会很有趣。你可以说,“为编译器做一个 C89 后端,让它处理一切”。我想知道 C89 中的 高效 后端是否可能用于 GCC。如果效率不高,那么对于嵌入式工作,它可能已经死了,“供应商的编译器中没有 C99”只是此类设备具有的几个严格限制之一......
【解决方案2】:

为了可维护性,我更喜欢使用明确标识变量的列表语法,如下所示:

counter_t counter = {.hour = 10, .min = 30, .sec = 47};

或用于返回内联例如:

return (struct counter_t){.hour = 10, .min = 30, .sec = 47};

我可以想象这样一种情况,即改变变量声明的顺序,如果你没有明确地识别你的变量,你将不得不通过所有的代码来修复变量的顺序。这种方式我认为它更干净,更具可读性

旁注

正如@AshleyDuncan 和@M.M 所说,此功能在C99 https://stackoverflow.com/a/12122261/2770195 之后从ISO C++ 中删除,但在gnu c++ 中受支持。

所以虽然你可以做到这一点就好了:

g++ -std=gnu++11 main.cpp -o main

如果您尝试上面的示例,这将引发错误:

# need an example. I was unable to find. Even clang++ supports it. If you know 
# one, please suggest an edit

如果您需要使用支持 ISO C++11 或更高版本但无法识别此 gnu 扩展的 C++ 编译器进行编译,您可能必须使用带有简单构造函数的类:

// backup workaround
// not cool
class gnuFTW {
public:
    int hour;
    int min;
    int sec;
    gnuFTW(int hour, int min, int sec) {
        this->hour = hour;
        this->min = min;
        this->sec = sec;
    }   
};

int main(int argc, const char * argv[]) {
    gnuFTW counter = gnuFTW(10,30,47);
    cout << counter.hour << endl;
    return 0;
}

【讨论】:

  • 我也喜欢这个,但如果您还希望使用 c++ 编译器进行编译,因为它是 c++ 不支持的仅限 C99 的功能,所以不太好。 stackoverflow.com/questions/12122234/…
  • 不知道。虽然很遗憾,但这是一个非常有用的功能。在这种情况下,我认为最好的方法是 Don Doerner 的解决方案:stackoverflow.com/a/14206226/2770195。简单地说:使用带有变量和单个初始化程序的类。这似乎不是一个好的做法,但它完全符合结构的作用。准备更新答案,谢谢提醒
  • 我很困惑,我刚刚编译了一个带有 -gnu++11 选项的示例:1drv.ms/i/s!ArNqKg0GFwIE0HVGDPPHvpEgaGrh。我错过了什么吗?
  • @AshleyDuncan 有什么想法吗?
  • @MuhsinFatih gnu++11 表示使用 GNU 扩展
猜你喜欢
  • 1970-01-01
  • 2013-05-06
  • 2021-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多