545

我想初始化一个结构元素,在声明和初始化中分开。这就是我所拥有的:

typedef struct MY_TYPE {
  bool flag;
  short int value;
  double stuff;
} MY_TYPE;

void function(void) {
  MY_TYPE a;
  ...
  a = { true, 15, 0.123 }
}

这是MY_TYPE按照 C 编程语言标准(C89、C90、C99、C11 等)声明和初始化局部变量的方式吗?或者有什么更好的或者至少可以工作的吗?

更新我最终得到了一个静态初始化元素,我根据需要设置了每个子元素。

4

16 回答 16

849

在 (ANSI) C99 中,您可以使用指定的初始化程序来初始化结构:

MY_TYPE a = { .flag = true, .value = 123, .stuff = 0.456 };

其他成员初始化为零:“省略的字段成员被隐式初始化,与具有静态存储持续时间的对象相同。” (https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

于 2008-12-01T13:39:37.323 回答
235

您可以使用复合文字来做到这一点。根据该页面,它适用于 C99(也算作ANSI C)。

MY_TYPE a;

a = (MY_TYPE) { .flag = true, .value = 123, .stuff = 0.456 };
...
a = (MY_TYPE) { .value = 234, .stuff = 1.234, .flag = false };

初始化器中的名称是可选的;你也可以写:

a = (MY_TYPE) { true,  123, 0.456 };
...
a = (MY_TYPE) { false, 234, 1.234 };
于 2008-12-01T13:28:09.003 回答
108

我看到您已经收到了有关 ANSI C 99 的答案,所以我将介绍一下 ANSI C 89。ANSI C 89 允许您以这种方式初始化结构:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = { 5, 2.2, "George" };
    return 0;
}

需要记住的重要一点是,当您在结构中初始化一个对象/变量时,它的所有其他变量都将被初始化为默认值。

如果您不初始化结构中的值,则所有变量都将包含“垃圾值”。

祝你好运!

于 2013-06-09T03:51:57.747 回答
48

a = (MYTYPE){ true, 15, 0.123 };

在 C99 中会做得很好

于 2008-12-01T13:27:22.280 回答
25

你几乎得到它...

MY_TYPE a = { true, 15, 0.123 };

快速搜索'struct initialize c'会 告诉我这个

于 2008-12-01T13:21:54.333 回答
23

C 编程语言标准ISO/IEC 9899:1999(通常称为 C99)允许使用指定的初始化程序来初始化结构或联合的成员,如下所示:

MY_TYPE a = { .stuff = 0.456, .flag = true, .value = 123 };

它在ISO/IEC 9899:1999 标准的paragraph 7部分中定义为:6.7.8 Initialization

如果指定者具有
. 标识符
,则当前对象(定义如下)应具有结构或联合类型,标识符应是该类型成员的名称。

请注意,paragraph 9同一部分指出:

除非另有明确说明,就本子条款而言,结构和联合类型对象的未命名成员不参与初始化。即使在初始化之后,结构对象的未命名成员也具有不确定的值。

然而,在 GNU GCC 实现中,省略的成员被初始化为零或类似零的类型适当值。如GNU GCC 文档的6.27 节指定初始化程序中所述:

省略的字段成员与具有静态存储持续时间的对象一样被隐式初始化。

根据官方博客文章C++ Conformance Roadmap ,Microsoft Visual C++ 编译器应支持自 2013 版以来的指定初始化程序。Initializing unions and structsMSDN Visual Studio 文档中的Initializers文章段落建议未命名的成员初始化为类似于 GNU GCC 的类似零的适当值。

已取代 ISO/IEC 9899:1999 的ISO/IEC 9899:2011标准(通常称为 C11)在6.7.9 Initialization. 它也保持paragraph 9不变。

已取代 ISO/IEC 9899:2011的新ISO/IEC 9899:2018标准(通常称为 C18)在第6.7.9 Initialization. 它也保持paragraph 9不变。

于 2016-06-08T11:43:11.043 回答
17

正如罗恩努尼所说

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = {5, 2.2, "George"};
    return 0;
}

需要记住的重要一点:当你在结构中初始化一个对象/变量时,它的所有其他变量都将被初始化为默认值。

如果您不初始化结构中的值(即,如果您只是声明该变量),那么所有variable.members将包含“垃圾值”,只有声明是本地的!

如果声明是全局或静态的(如本例),所有未初始化variable.members的将自动初始化为:

  • 0对于整数和浮点
  • '\0'for char(当然这和 , 是一样的0char是整数类型)
  • NULL为指针。
于 2013-09-04T09:37:18.910 回答
12

添加到所有这些好的答案中,总结了如何在 C 中初始化结构(联合和数组),特别关注设计的初始化程序。

标准初始化

struct point 
{
    double x;
    double y;
    double z;
}

p = {1.2, 1.3}; 

指定初始化器

指定初始化器从 ISO C99 开始出现,它是一种不同且更动态的方式,用于在初始化时在 C 中进行初始化structunion或在array.

与标准初始化的最大区别是您不必按固定顺序声明元素,也可以省略元素。

来自GNU 指南

标准 C90 要求初始值设定项的元素以固定顺序出现,与被初始化的数组或结构中元素的顺序相同。

在 ISO C99 中,您可以按随机顺序给出元素,指定它们适用的数组索引或结构字段名称,GNU C 也允许将其作为 C90 模式的扩展


例子

1.数组索引

标准初始化

int a[6] = { 0, 0, 15, 0, 29, 0 };

指定初始化

int a[6] = {[4] = 29, [2] = 15 }; // or
int a[6] = {[4]29 , [2]15 }; // or
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };

2.结构或联合:

标准初始化

struct point { int x, y; };

指定初始化

struct point p = { .y = 2, .x = 3 }; or
struct point p = { y: 2, x: 3 };

3.将命名元素与连续元素的普通C初始化结合起来:

标准初始化

int a[6] = { 0, v1, v2, 0, v4, 0 };

指定初始化

int a[6] = { [1] = v1, v2, [4] = v4 };

4. 其他:

标记数组初始值设定项的元素

int whitespace[256] = { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
                        ['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };

在“=”之前编写一系列“.fieldname”和“[index]”指示符以指定要初始化的嵌套子对象

struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };

指南

于 2021-01-03T04:45:42.543 回答
5

我不喜欢这些答案中的任何一个,所以我自己做了。我不知道这是否是 ANSI C,它只是默认模式下的 GCC 4.2.1。我永远记不起括号,所以我从我的数据子集开始,并与编译器错误消息作斗争,直到它关闭。可读性是我的首要任务。

// in a header:
typedef unsigned char uchar;

struct fields {
  uchar num;
  uchar lbl[35];
};

// in an actual c file (I have 2 in this case)
struct fields labels[] = {
  {0, "Package"},
  {1, "Version"},
  {2, "Apport"},
  {3, "Architecture"},
  {4, "Bugs"},
  {5, "Description-md5"},
  {6, "Essential"},
  {7, "Filename"},
  {8, "Ghc-Package"},
  {9, "Gstreamer-Version"},
  {10, "Homepage"},
  {11, "Installed-Size"},
  {12, "MD5sum"},
  {13, "Maintainer"},
  {14, "Modaliases"},
  {15, "Multi-Arch"},
  {16, "Npp-Description"},
  {17, "Npp-File"},
  {18, "Npp-Name"},
  {19, "Origin"}
};

数据可能以制表符分隔文件的形式开始存在,您可以搜索替换以将其插入其他内容。是的,这是 Debian 的东西。因此,一对外部 {} (指示数组),然后是内部每个结构的另一对。之间用逗号。把东西放在标题中并不是绝对必要的,但我的结构中有大约 50 个项目,所以我希望它们放在一个单独的文件中,既可以避免我的代码混乱,也更容易替换。

于 2016-05-12T17:14:03.263 回答
5

这可以通过不同的方式完成:

MY_TYPE a = { true, 1, 0.1 };

MY_TYPE a = { .stuff = 0.1, .flag = true, .value = 1 }; //designated initializer, not available in c++

MY_TYPE a;
a = (MY_TYPE) { true,  1, 0.1 };

MY_TYPE m (true, 1, 0.1); //works in C++, not available in C

此外,您可以在声明结构时定义成员。

#include <stdio.h>

struct MY_TYPE
{
    int a;
    int b;
}m = {5,6};

int main()
{
    printf("%d  %d\n",m.a,m.b);    
    return 0;
}
于 2020-08-13T09:36:41.707 回答
3
void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}
于 2008-12-01T13:19:49.877 回答
3

如果 MS 还没有更新到 C99,MY_TYPE a = { true,15,0.123 };

于 2014-04-20T19:39:46.633 回答
3

我找到了另一种初始化结构的方法。

结构:

typedef struct test {
    int num;
    char* str;
} test;

初始化:

test tt = {
    num: 42,
    str: "nice"
};

根据 GCC 的文档,此语法自 GCC 2.5 以来已过时

于 2015-12-04T03:15:55.490 回答
1

C中的结构可以这样声明和初始化:

typedef struct book
{
    char title[10];
    char author[10];
    float price;
} book;

int main() {
    book b1={"DS", "Ajay", 250.0};

    printf("%s \t %s \t %f", b1.title, b1.author, b1.price);

    return 0;
}
于 2017-09-06T18:38:28.550 回答
0

我已经阅读了用于初始化聚合类型的 Microsoft Visual Studio 2015 文档,所有形式的初始化{...}都在此处进行了说明,但此处未提及使用点进行初始化,名为“指定器”。它也不起作用。

C99 标准第 6.7.8 章初始化解释了指示符的可能性,但在我看来,对于复杂的结构并不是很清楚。C99 标准为pdf 。

在我看来,这可能会更好

  1. 对所有静态数据使用= {0};-initialization。机器代码的工作量更少。
  2. 使用宏进行初始化,例如

    typedef MyStruct_t{ int x, int a, int b; } MyStruct; define INIT_MyStruct(A,B) { 0, A, B}

宏可以调整,它的参数列表可以独立于改变的结构内容。如果应该初始化更少的元素是合适的。它也适用于嵌套结构。3. 一个简单的形式是: 在子程序中初始化:

void init_MyStruct(MyStruct* thiz, int a, int b) {
  thiz->a = a; thiz->b = b; }

这个例程看起来像 C 中的面向对象。使用thiz,而不是this用 C++ 编译它!

MyStruct data = {0}; //all is zero!
init_MyStruct(&data, 3, 456);
于 2018-08-12T14:10:33.627 回答
-3

我一直在寻找一种初始化我的结构的好方法,我必须使用下面的(C99)。这让我可以像普通类型一样初始化单个结构或结构数组。

typedef struct {
    char *str;
    size_t len;
    jsmntok_t *tok;
    int tsz;
} jsmn_ts;

#define jsmn_ts_default (jsmn_ts){NULL, 0, NULL, 0}

这可以在代码中用作:

jsmn_ts mydata = jsmn_ts_default; /* initialization of a single struct */

jsmn_ts myarray[10] = {jsmn_ts_default, jsmn_ts_default}; /* initialization of
                                                    first 2 structs in the array */
于 2018-12-02T17:46:09.513 回答