C 是否可以使用指定的起爆器使油田单元化?

C 是否可以使用指定的起爆器使油田单元化?,c,performance,c99,micro-optimization,designated-initializer,C,Performance,C99,Micro Optimization,Designated Initializer,考虑以下结构和函数来创建结构: #定义最大元素1000 结构材料{ 双重魔法; bool是有效的[MAX_ELEMS]; 双值[最大元素]; }; struct stuff make_stuff(双重魔法){ 返回(struct stuff){ .魔术 }; } 在我的例子中,我需要将stuff.magic初始化为给定的值,stuff.is\u有效数组初始化为零,但我不想初始化stuff.value(因为它们由stuff.is\u有效并在以后按需初始化) 我可以用指定的初始化器实现这一点吗 我

考虑以下结构和函数来创建结构:

#定义最大元素1000
结构材料{
双重魔法;
bool是有效的[MAX_ELEMS];
双值[最大元素];
};
struct stuff make_stuff(双重魔法){
返回(struct stuff){
.魔术
};
}
在我的例子中,我需要将
stuff.magic
初始化为给定的值,
stuff.is\u有效
数组初始化为零,但我不想初始化
stuff.value
(因为它们由
stuff.is\u有效
并在以后按需初始化)

我可以用指定的初始化器实现这一点吗


我知道我可以实现它,但这更难看,更容易出错(除其他原因外,因为我现在需要显式地将
东西归零。是否有效,可能有一个memset)。

任何未专门初始化的字段都将用零填充


所以,不,如果你初始化任何字段,它们都会得到一些东西(即使只是零)

任何没有特别初始化的字段都会被零填充

所以,不,如果你初始化任何字段,它们都会得到一些东西(即使只是零)

这只能通过“正常”赋值和memset来完成

struct stuff make_stuff(double magic) 
{  
    struct stuff s;
    memset(s.is_valid, 0, sizeof(s.is_valid));
    s.magic = magic;
    return s;
} 
但是,如果您正在寻找返回如此大的结构的效率,那就没有任何意义,因为当结构通过值传递时,它将被完整复制两次

最好将指针传递给结构

struct stuff *make_stuff(struct stuff *s, double magic) 
{  
    memset(s -> is_valid, 0, sizeof(s -> is_valid));
    s -> magic = magic;
    return s;
} 
它只能通过“普通”赋值和memset完成

struct stuff make_stuff(double magic) 
{  
    struct stuff s;
    memset(s.is_valid, 0, sizeof(s.is_valid));
    s.magic = magic;
    return s;
} 
但是,如果您正在寻找返回如此大的结构的效率,那就没有任何意义,因为当结构通过值传递时,它将被完整复制两次

最好将指针传递给结构

struct stuff *make_stuff(struct stuff *s, double magic) 
{  
    memset(s -> is_valid, 0, sizeof(s -> is_valid));
    s -> magic = magic;
    return s;
} 

只要
make\u stuff
可以内联,按值返回就可以了。然后,这是一种编写包装器的好方法,可用于
struct stuff foo=make_stuff(1.0)@PeterCordes-内联并不总是必要的,至少对于合理的ABI来说是这样。调用者将传递一个指向返回值区域的指针,调用者将直接填写返回值,不需要在调用者中进行复制。这种“优化”甚至发生在的
-O0
。诚然,它在所有场景中都不起作用(如C++所示,它有附加的语言使它成为可能)。@ BeeOnRope:HMM,内联也不总是足够的。显示当arg为
1.0
而不是
0.
时,gcc错过了优化,仍然执行9008字节的memcpy,而clang没有。因此,显式地获取输出arg,而不是通过调用约定隐式地获取输出arg,显然更安全。@PeterCordes-这当然很奇怪。在任何情况下,我的用法都是
struct stuff s=make(…)
,也就是说,赋值给一个新定义的对象,这似乎问题不大。@PeterCords示例的琐碎性使内联成为可能。只要
make\u stuff
可以内联,按值返回就可以了。然后,这是一种编写包装器的好方法,可用于
struct stuff foo=make_stuff(1.0)@PeterCordes-内联并不总是必要的,至少对于合理的ABI来说是这样。调用者将传递一个指向返回值区域的指针,调用者将直接填写返回值,不需要在调用者中进行复制。这种“优化”甚至发生在的
-O0
。诚然,它在所有场景中都不起作用(如C++所示,它有附加的语言使它成为可能)。@ BeeOnRope:HMM,内联也不总是足够的。显示当arg为
1.0
而不是
0.
时,gcc错过了优化,仍然执行9008字节的memcpy,而clang没有。因此,显式地获取输出arg,而不是通过调用约定隐式地获取输出arg,显然更安全。@PeterCordes-这当然很奇怪。在任何情况下,我的用法都是
struct stuff s=make(…)
,即赋值给一个新定义的对象,这似乎问题不大。@PeterCordes示例的简单性使内联成为可能。