我被一个数组/结构的默认阅读有关初始化值,并有这样的疑问:
是memset(&mystruct, 0, sizeof mystruct)
相同mystruct = { 0 };
?
如果不是,有什么区别呢?
我被一个数组/结构的默认阅读有关初始化值,并有这样的疑问:
是memset(&mystruct, 0, sizeof mystruct)
相同mystruct = { 0 };
?
如果不是,有什么区别呢?
是memset的(&MYSTRUCT,0,的sizeof MYSTRUCT)相同MYSTRUCT = {0}; ?
没有。
memset(&mystruct, 0, sizeof mystruct) ;
...会告诉编译器调用,我们期望在执行过程中MYSTRUCT的数据将设置为零的功能。
mystruct = { 0 };
...将设置告诉编译器本身的数据设置为零,这意味着它将会:
请注意, 是编译器可以优化memset的成编译时间指令( ),但我不会依赖于作为memset
是从运行时库中的函数,而不是一些语言内在的( )。
从C ++来了,我自己的观点是,你越可以在编译做,更多的编译器知道在编译的时候,执行甚至开始之前,更好的:它使编译器可能优化代码和/或产生警告/错误。
在目前的情况下,使用mystruct = { 0 };
符号来初始化struct
总是比使用memset的,因为它是非常简单的C语言编写错误的事情有一个更安全memset
没有编译器抱怨。
下面的例子表明,很容易比它似乎做的代码做不同的事情:
// only the 1st byte will be set to 0
memset(&mystruct, 0, sizeof(char)) ;
// will probably overrun the data, possibly corrupting
// the data around it, and you hope, crashing the process.
memset(&mystruct, 0, sizeof(myLARGEstruct)) ;
// will NOT set the data to 257. Instead it will truncate the
// integer and set each byte to 1
memset(&mystruct, 257, sizeof(mystruct)) ;
// will set each byte to the value of sizeof(mystruct) modulo 256
memset(&mystruct, sizeof(mystruct), 0) ;
// will work. Always.
mystruct = { 0 } ;
这是一个完全迂腐的答案,但鉴于空指针的内部表示不guaranted为0
的行为memset
对大括号初始化会有所不同( memset
会做错误的事情)。 不过,我从来没有听说过了这个冒昧地对空非全为0的位模式实现的。
理论上有区别。 该初始化器不需要初始化填充,如果有一些mystruct
。 例如:
int main(void)
{
struct mystruct {
char a;
int what;
} s = {0};
}
可能包含:
00 xx yy zz 00 00 00 00
其中XX YY和ZZ是在堆栈上,其中未定义字节。 编译器允许这样做。 这表示,在所有的实践中,我还没有遇到一个编译器,这样做呢。 最理智的实现将语义处理像这种情况下memset
。
memset(&mystruct, 0, sizeof mystruct);
is a statement. It can be executed any time where mystruct
is visible, not just at the point where it's defined.
mystruct = { 0 };
is actually a syntax error; { 0 }
is not a valid expression.
(I'll assume that mystruct
is an object of type struct foo
.)
What you're probably thinking of is:
struct foo mystruct = { 0 };
where { 0 }
is an initializer.
If your compiler supports it, you can also write:
mystruct = (struct foo){ 0 };
where (struct foo){ 0 }
is a compound literal. Compound literals were introduced in C99; some C compilers, particularly Microsoft's probably don't support it. (Note that the (struct foo)
is not a cast operator; it looks similar to one, but it's not followed by an expression or parenthesized type name. It's a distinct syntactic construct.)
If your compiler doesn't support compound literals, you can work around it by declaring a constant:
const struct foo foo_zero = { 0 };
struct foo mystruct;
/* ... */
mystruct = foo_zero;
So that's how they differ in syntax and in where you can use them. There are also semantic differences.
The memset
call sets all the bytes that make up the representation of mystruct
to all zeros. It's a very low-level operation.
On the other hand, the initializer:
struct foo mystruct = { 0 };
sets the first scalar subcomponent of mystruct
to 0, and sets all other subcomponents as if they were initialized as static objects -- i.e., to 0. (It would be nice if there were a cleaner struct foo mystruct = { };
syntax to do the same thing, but there isn't.)
The thing is, setting something to 0
isn't necessarily the same thing as setting its representation to all-bits-zero. The value 0
is converted to the appropriate type for each scalar subcomponent.
For integers, the language guarantees that all-bits-zero is a representation of 0
(but not necessarily the only representation of 0
). It's very likely that setting an integer to 0
will set it to all-bits-zero, but it's conceivable that it could set it to some other representation of 0
. In practice, that would only happen with a deliberately perverse compiler.
For pointers, most implementations represent null pointers as all-bits-zero, but the language doesn't guarantee that, and there have been real-world implementations that use some other representation. (For example, using something like all-bits-one might make null pointer dereferences easier to detect at run time.) And the representation may differ for different pointer types. See section 5 of the comp.lang.c FAQ.
Similarly, for floating-point types, most implementations represent 0.0
as all-bits-zero, but the language standard doesn't guarantee it.
You can probably get away with writing code that assumes the memset
call will set all subcomponents to zero, but such code is not strictly portable -- and Murphy's Law implies that the assumption will fail at the most inconvenient possible moment, perhaps when you port the code to an important new system.