如何根据C编程语言标准初始化结构

cri*_*nge 435 c struct initialization

我想初始化一个struct元素,在声明和初始化中拆分.这就是我所拥有的:

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

void function(void) {
  MY_TYPE a;
  ...
  a = { true, 15, 0.123 }
}
Run Code Online (Sandbox Code Playgroud)

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

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

phi*_*ant 696

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

MY_TYPE a = { .flag = true, .value = 123, .stuff = 0.456 };
Run Code Online (Sandbox Code Playgroud)

编辑:其他成员初始化为零:"省略的字段成员与具有静态存储持续时间的对象隐式初始化." (https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html)

  • 太好了,谢谢.你甚至可以嵌套em:static oxeRay2f ray = {.unitDir = {.x = 1.0f,.y = 0.0f}}; (83认同)
  • 这根本不回答这个问题.OP希望将初始化与声明分开. (4认同)
  • C99!= ANSI C-因此,这在C89或C90中均不起作用。 (3认同)
  • C99是ANSI C,请参阅[this](/sf/ask/1204459791/) (2认同)
  • @CutbertoOcampo我知道现在发生了什么。最初的问题是在ANSI C中寻求解决方案,显然他只想为C89提供答案。在2016年,对问题进行了编辑,并删除了“ ANSI C”,这使得现在很难理解为什么此答案和注释提到“(ANSI)C99”。 (2认同)

Ces*_*arB 191

你可以用复合文字来做.根据该页面,它适用于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 };
Run Code Online (Sandbox Code Playgroud)

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

a = (MY_TYPE) { true,  123, 0.456 };
...
a = (MY_TYPE) { false, 234, 1.234 };
Run Code Online (Sandbox Code Playgroud)

  • 这有点棘手。很多次(有些成功)我尝试使用指定的初始化程序。但是,现在才很清楚(由于您和@philant的示例),如果在对象创建时未使用初始化程序,则必须存在强制转换。但是,我现在也了解到,如果在对象创建以外的其他时间使用初始化程序(如您的示例中所示),则它被称为“复合文字”,而不是严格地称为“指定的初始化程序”。https://ideone.com/Ze3rnZ (2认同)

小智 88

我看到你已经收到了关于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;
}
Run Code Online (Sandbox Code Playgroud)

需要记住的重要一点是,即使在结构中初始化一个对象/变量,其所有其他变量也将初始化为默认值.

如果不初始化结构中的值,则所有变量都将包含"垃圾值".

祝好运!

  • 是否可以在初始化中使用变量? (3认同)
  • @Cyan用于具有自动存储持续时间的对象。参见http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf中的6.7.9 13)。对于全局对象,几乎仅限于文字。您甚至不能使用其他全局对象,即使它们是const。 (2认同)

qrd*_*rdl 38

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

在C99会很好


Kie*_*eli 18

你几乎得到了......

MY_TYPE a = { true,15,0.123 };
Run Code Online (Sandbox Code Playgroud)

快速搜索'struct initialize c' 向我展示了这一点

  • 嗯...你的编码规则故意不好吗?也许你应该把编写它们的人介绍给"资源获取是初始化"(http://en.wikipedia.org/wiki/RAII) (8认同)
  • 初始化只能在声明时发生.这就是'初始化'的意思.否则,您允许将未定义的值作为变量/结构的初始值,然后再分配值. (7认同)

PF4*_*lic 16

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

MY_TYPE a = { .stuff = 0.456, .flag = true, .value = 123 };
Run Code Online (Sandbox Code Playgroud)

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

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

请注意,paragraph 9同一部分说明:

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

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

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

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

已取代ISO/IEC 9899:1999的ISO/IEC 9899:2011标准(通常称为C11)保留了部分下的指定初始化器6.7.9 Initialization.它也保持paragraph 9不变.

新的ISO/IEC 9899:2018标准(通常称为C18)已取代ISO/IEC 9899:2011保留了部分下的指定初始化器6.7.9 Initialization.它也保持paragraph 9不变.

  • 最初我建议将其作为对已接受答案的编辑,但它被拒绝了.因此我将其作为答案发布. (2认同)

r_g*_*yal 14

正如Ron Nuni所说:

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

int main(void) {
    Item item = {5, 2.2, "George"};
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

需要记住的重要一点是:在结构中甚至初始化一个对象/变量时,所有其他变量都将初始化为默认值.

如果你没有初始化你的struct中的值(即如果你只是声明那个变量),那么只有声明是本地的,所有都variable.members将包含"垃圾值" !

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

  • 0 对于整数和浮点数
  • '\0'for char(当然这0和它char是一样的,是一个整数类型)
  • NULL 指针.


Fed*_*Baù 9

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

标准初始化

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

p = {1.2, 1.3}; 
Run Code Online (Sandbox Code Playgroud)

指定初始化器

指定初始化想出了自ISO C99,是一种不同的,更动态的方式在初始化时在C初始化structunionarray

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

来自GNU 指南

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

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


例子

1. 数组索引

标准初始化

int a[6] = { 0, 0, 15, 0, 29, 0 };
Run Code Online (Sandbox Code Playgroud)

指定初始化

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 };
Run Code Online (Sandbox Code Playgroud)

2. 结构体或联合体:

标准初始化

struct point { int x, y; };
Run Code Online (Sandbox Code Playgroud)

指定初始化

struct point p = { .y = 2, .x = 3 }; or
struct point p = { y: 2, x: 3 };
Run Code Online (Sandbox Code Playgroud)

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

标准初始化

int a[6] = { 0, v1, v2, 0, v4, 0 };
Run Code Online (Sandbox Code Playgroud)

指定初始化

int a[6] = { [1] = v1, v2, [4] = v4 };
Run Code Online (Sandbox Code Playgroud)

4. 其他:

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

int whitespace[256] = { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
                        ['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };
Run Code Online (Sandbox Code Playgroud)

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

struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };
Run Code Online (Sandbox Code Playgroud)

指南


Ala*_*rey 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"}
};
Run Code Online (Sandbox Code Playgroud)

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

  • 没有关于结构数组初始化的问题!我的意思是,您的答案包含开销。 (3认同)

Sat*_*ish 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
Run Code Online (Sandbox Code Playgroud)

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

#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;
}
Run Code Online (Sandbox Code Playgroud)