抱歉,如果这是重复的,在这种情况下,我找不到要搜索的正确关键字。
这是参考我正在处理的一些旧(MUD)代码,粘贴在下面。我对下面代码的 foo_zero
和 *foo = foo_zero
部分的用途感到困惑。这是它在整个代码库中使用的模式。我的猜测是,这是一种无需显式设置即可将 foo
的所有成员初始化为零/NULL 的方法。
typedef struct FOO {
int buzz;
char *bazz;
} FOO;
FOO *init_foo(void)
{
static FOO foo_zero;
FOO *foo;
foo = malloc(sizeof(*foo));
*foo = foo_zero; // <-- why?
return foo;
}
答案 0 :(得分:2)
是的,线条
static FOO foo_zero;
和
*foo = foo_zero;
安排 struct FOO
分配的 init_foo()
的每个新实例都像有人说的那样初始化
struct FOO new_foo = { 0 };
具体来说,所有整数字段将初始化为 0,所有浮点字段将初始化为 0.0,所有指针字段将初始化为空指针(又名 NULL
,或 nullptr
in C++)。
这是一种很好的技术,因为它比其他技术更简单,而且严格来说更便于携带。
在评论中讨论了关于其他可能性的讨论
foo = malloc(sizeof(*foo));
memset(foo, 0, sizeof(*foo));
或
foo = calloc(1, sizeof(*foo));
这两种方法都会将全新的 struct FOO
初始化为 all-bits-0。这里有一个微妙的问题——它是如此微妙以至于许多程序员根本不会称之为问题——是处理器和/或操作系统在理论上可能表示一个浮点值 0.0 或一个 null指针,具有除 all-bits-0 以外的其他位模式。
但是如果你使用这样的处理器,那么做
float f = 0;
或
char *p = 0;
会做正确的事情,用正确的零值初始化变量,即使它不是全位 0。对于诸如 struct FOO
之类的聚合,执行
struct FOO new_foo = { 0 };
等价于用 0 显式初始化它的每个成员,这意味着您得到正确的零值,即使那不是全部位 0。最后,任何时候你声明一个具有静态持续时间的变量,如
static FOO foo_zero;
您会得到一个隐式初始化,就像您说 = { 0 };
一样,因此默认(静态)初始化也无论如何都会为您提供正确的零值。
如果您仍然对 calloc
的 all-bits-0 保证感到好奇,您可以在 question 7.31 的 C FAQ list 中阅读更多相关内容。
答案 1 :(得分:1)
其实这个声明
static FOO foo_zero;
相当于下面的
static FOO foo_zero = { .buzz = 0, .bazz = 0 };
所以在这个赋值语句中
*foo = foo_zero;
指针 foo 所指向的对象以与静态变量 foo_zero 相同的方式进行零初始化。
该函数返回一个指向零初始化对象的指针。
对于这个简单的情况,如果您使用 malloc 代替 malloc,您可以获得几乎相同的效果 使用 calloc。
FOO *init_foo(void)
{
return calloc( 1, sizeof( struct FOO ) );;
}
但有时需要进行非平凡的初始化。所以你展示的方法是有意义的。例如
struct FOO
{
size_t n;
char s[10];
};
struct FOO * init_foo( void )
{
static struct FOO default_foo = { .n = 6, .s = "Hello" };
struct FOO *foo = malloc( sizeof( *foo ) );
if ( foo ) *foo = default_foo;
return foo;
}
答案 2 :(得分:0)
为什么要复杂化?
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct {
int buzz;
char *bazz;
} FOO;
上面的 init_foo()
实际上只是返回在堆上创建的新 foo。都干净。所以让我们这样做:
static inline FOO * new_foo(void)
{
return calloc(1,sizeof(FOO));
}
使用和检查:
int main (void)
{
FOO * foo = new_foo();
printf("buzz: %d, bazz: %s", foo->buzz, foo->bazz );
free(foo);
return 42;
}
Godbolt 显示新的结构 FOO 很好地为空
Program returned: 42
buzz: 0, bazz: (null)