From this comment in GCC bug #53119:
In C,
{0}
is the universal zero initializer equivalent to C++'s{}
(the latter being invalid in C). It is necessary to use whenever you want a zero-initialized object of a complete but conceptually-opaque or implementation-defined type. The classic example in the C standard library ismbstate_t
:mbstate_t state = { 0 }; /* correctly zero-initialized */
versus the common but nonportable:
mbstate_t state; memset(&state, 0, sizeof state);
It strikes me as odd that the latter version could be unportable (even for implementation-defined types, the compiler has to know the size). What is the issue here and when is a memset(x, 0, sizeof x)
unportable?
memset can be faster since it is written in assembler, whereas std::fill is a template function which simply does a loop internally.
AFAIK memset isn't required to check for NULL, so if the malloc fails you'll zero size bytes starting from address 0.
memset() will blindly write to the specified address for the number of specified bytes, regardless of what it might be overwriting. It is up to the programmer to ensure that only valid memory is written to.
memset predates (by quite a bit) the addition of function prototypes to C. Without a prototype, you can't pass a char to a function -- when/if you try, it'll be promoted to int when you pass it, and what the function receives is an int .
The most common application of memset () is to set a block of memory to "all 0 bytes" so as to erase any information that memory previously contained.
Depending on the implementation of memset () and the size of the block of memory being zeroed, this can be faster than simply setting all elements to 0 in code. (memset () is usually implemented in assembly language, and can use operations such as the x86 "string" instructions or the ARM "multiple register store" to speed it up.)
After memset (): GeeksForGeeks........programming geeks. Explanation: (str + 13) points to first space (0 based index) of the string “GeeksForGeeks is for programming geeks.”, and memset () sets the character ‘.’ starting from first ‘ ‘ of the string up to 8 character positions of the given string and hence we get the output as shown above.
Many versions of memset can use a "bit blit" operation in hardware to set large groups of memory to the same value essentially instantly - or at least far faster than you could possibly do with a code-level loop - especially if you're setting the value to zero or 0xFF. How can one use memset () in C++ for two dimensional arrays?
memset(p, 0, n)
sets to all-bits-0.
An initializer of { 0 }
sets to the value 0.
On just about any machine you've ever heard of, the two concepts are equivalent.
However, there have been machines where the floating-point value 0.0 was not represented by a bit pattern of all-bits-0. And there have been machines where a null pointer was not represented by a bit pattern of all-bits-0, either. On those machines, an initializer of { 0 }
would always get you the zero initialization you wanted, while memset
might not.
See also question 7.31 and question 5.17 in the C FAQ list.
Postscript: One other difference, as pointed out by @ryker: memset
will set any "holes" in a padded structure to 0, while setting that structure to { 0 }
might not.
The reason for this has to do with how types are represented.
Section 6.7.9p10 of the C standard describes how fields are initialized as follows:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized
explicitly, then:
if it has pointer type, it is initialized to a null pointer;
if it has arithmetic type, it is initialized to (positive or unsigned) zero;
if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits
And p21 also states:
If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration
The difference between this and setting all bytes to zero is that some of the above values may not necessarily be represented by all bits zero.
For example, there are some architectures where the address 0 is a valid address. This means that a null pointer is not represented as all bits zero. (Note: (void *)0
is specified as a null pointer constant by the standard, however the implementation will treat this as whatever the representation of a null pointer is)
The standard also doesn't mandate a particular representation for floating point types. While the most common representation, IEEE754, does use all bits 0 to represent the value +0, this is not necessarily true for other representations.
Noting a difference in behavior between the two methods...
In ...= {0};
if padding bytes exist, they will not be cleared.
But a call to memset()
will clear padding.
From here
"Possible implementation of mbstate_t is a struct type holding an array representing the incomplete multibyte character, an integer counter indicating the number of bytes in the array that have been processed, and a representation of the current shift state."
In the case mbstate_t
is implemented as a struct
it is notable that {0}
will not set padding bytes that may exist to zero
, making the following assumption debatable:
mbstate_t state = { 0 }; /* correctly zero-initialized */
memset()
however does include padding bytes.
memset(state , 0, sizeof state);//all bytes in memory region of test will be cleared
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With