Fog Creek Software
g
Discussion Board




memset usage

Can I use memset to initializing a struct array ?

I doubt that because memset flushs
a continuous area by an address and a length,
it may not be suitable for initializing a struct, which may use
non-continuous memeory to fit its members.

Li Hu
Wednesday, March 24, 2004

I think the problem would be not with the area being continuous or not (I believe it is always continuous, perhaps with some padding that increases it's size) but with representation of numbers.

I mean, floating point numbers may not be 0.0 if you fill them with 0x00 bytes on some platforms.

TomA
Wednesday, March 24, 2004

memset always works for initializing a struct to zero:

struct foo { ... } f;
memset( &f, 0, sizeof(f) );

or

struct foo { ... } *pf;
pf = (struct foo*) malloc( sizeof(*pf) );
memset( pf, 0, sizeof(*pf) );


The examples will always work properly.  The struct is always allocated in contiguous virtual memory.

hoser
Wednesday, March 24, 2004

Use calloc as a shorthand for malloc+memset.

Jordan
Wednesday, March 24, 2004

What language are you coding in?

In C++, it's likely a bad idea.  It won't hurt to initialize the padding bytes, but if parts of the struct are "somewhere else" those aren't going to be initialized, so you've got... well, what have you got?  An array of default constructed structs with the contiguous bits clobbered?  That doesn't sound useful (especially if the contiguous bits include a vtable pointer, or a non POD data member).

If you are programmin in C, then the elements of the array are not initialized by default, so I suppose you are no worse off than leaving the array uninitialized.

I do wonder what sort of constraint you are up against that you would choose to use memset as your initializer.

Danil
Wednesday, March 24, 2004

hoser wrote:
"memset always works for initializing a struct to zero"

Um. No, it really isn't guaranteed to. If your struct only contains integer fields, then it'll work. As has already been mentioned, floating-point fields will not necessarily be  0.0 if they are initialized by zeroing memory. A pointer field won't necessarily be initialized to a useful value, either.

-Mark

Mark Bessey
Wednesday, March 24, 2004

As long as your structure doesn't have any methods (i.e. it is a plain C structure) is safe.

BTW, I think that the members of a structure (or class for that matter) are always stored contiguously in memory, that is not the reason why you cannot use memset; the reason why you cannot use memset for an object of type class (or structure with methods) is that the class/structure contains hidden data (like pointers to a vtable or where the methods bodies are found in memory, etc) that would get overwritten if memset is used.

DP
Wednesday, March 24, 2004

Note that if the struct includes data members that are pointers, then memset will initialize the pointers ... it won't initialize the memory that the pointers are pointing to.

Christopher Wells
Wednesday, March 24, 2004


On what architecture would memsetting a double not yield zero?

I know it's conceivable that you might get something else (what? 10? -1?) but why would anybody design such a thing?

It is safe to use memset on plain-ol' structures (even in C++), You have to be very careful not to use it on classes (Anyway, classes should have a constructor/initializer that places the object in an appropriate state).

njkayaker
Wednesday, March 24, 2004

Floats are similar to 1.3 * 10^5 sort of notation, except they are base 2.  Because they are base 2, the first digit on the 1.3 part is always 1.  If it were 0, you could shift the digits till there was a 1, and add the number of shifts to the exponent.  Zero itself is the only exception.  Because it is (almost) always one, you can imply it.  With this simplistic representation, binary 0 would end up being 1.0 * 2^0, or the number 1.  Of course, floats can't be quite that simple, because it leaves you no way to represent 0.  With the ieee standard the entire 0 exponent is a special case, and I think the all binary 1 for either exponent or mantissa are also special cases.  Don't remember entirely.  But there plenty of systems that aren't ieee, so who knows how each system represents the parts that don't fit in nicely with the simplistic model.  IEEE has all sorts of special values, NAN (signalling and nonsignalling), Infinities and Infinitessimals.

Keith Wright
Wednesday, March 24, 2004


Excepting the following, the above is true.

0*10^0 = 0*1 = 0.

njkayaker
Wednesday, March 24, 2004

There are two parts to a float: the mantissa and the exponent. The mantissa can be 0. A zero mantissa means zero.

njkayaker
Wednesday, March 24, 2004

yeah, I said "Zero itself is the only exception".  Had trouble figuring out the best place in the paragraph to put that.  I went looking for examples of platforms where binary 0 does not represent float or double 0.0.  Found a post by James Kanze that says "But I know of no real architecture where all 0 bits in a double is not interpreted as 0.0".  found one guy who mentioned some antique computer of K & R sort of vintage.  One thing you can do is do the memset, and then check one value to see if it worked.  (though if all 0 turned out to be a signalling NAN, you could throw an exception) . You could do the same with pointers, too, I'd imagine. (NULL is not necessarily all 0 bits, even though NULL == 0 is true!)

I should probably add an "I am not a language lawyer" disclaimer.

Keith Wright
Wednesday, March 24, 2004

njkayaker:  If you look at the IEEE standard, there are a bunch of different values with a 0 mantissa.  and if you read my first post, you'd see that 1.0 x 2 ^ x is usually represented by a binary 0 mantissa.  If you look up the definition of matissa, you will see that it is the remainder after a logorithm.  in 9.3 x 10^ 7, the mantissa is .3

Keith Wright
Wednesday, March 24, 2004

You can memset it to 0 only if the members are fundamental types (int, char, char[]), that is they are not pointers holding valid references to objects (allocated char*).

coresi
Wednesday, March 24, 2004

Also, depending on architecture, the NULL pointer may be represented by something else than a bunch of zero bits. Strange but true.

I can't remember specific examples, although I know they do exist.

Klodd the Insensitive
Wednesday, March 24, 2004

The C standard says that NULL is the same as zero. (Note that zero may be a valid memory address in the underlying architecture but you'll likely have problems using it in C. It is acceptible to use 0 instead of NULL.

A zero filled (i.e. memsetted) double is zero (i.e. 0.0) and is intentionally so. (There may be rare, old architectures where this is not true.)

I sure hope that, with "One thing you can do is do the memset, and then check one value to see if it worked", you don't mean "though it works on one architecture, it might not work on another". One would want it to work on all architectures and (excepting the rare, old stuff) it will.

As far as I know, the IEEE NAN is a non-zero bit pattern. It's also a cross architecture standard.

*Memsetting a structure is safe.*. You can *always* memset a structure. If the structure contains pointers, the pointer values are set to zero (i.e. an invalid address, i.e. NULL).

See the following code example (which behaves the same on Windows and HPUX):

    double dDouble1 = 0.0;
    double dDouble2 = 10;

    memset(&dDouble2, 0, sizeof(dDouble2));

    if(memcmp(&dDouble1, &dDouble2, sizeof(dDouble2)) == 0)
    {
        dDouble2 = 2.0; // Gets executed
    }

    dDouble2 = 0.0;
    if(memcmp(&dDouble1, &dDouble2, sizeof(dDouble2)) == 0)
    {
        dDouble2 = 2.0; // Gets executed
    }

njkayaker
Wednesday, March 24, 2004

This talk of floating point values is double talk (pun intended). If he is using memset then by definition he wants to set the _memory content_ to <whatever value> (I don't why you are all assuming zero, the OP never said that). That that may translate to variable values which do not equate to <whatever value> is not the question, and depends on what the content of the . The answer to the question asked is "In C and C++, yes you can."

Hell, you can even do things like this:
class foo
{
public:
    foo(){m_i=2;};

    int m_i;
};

struct struct_foo
{
    foo f;
};

int main(int argc, char* argv[])
{
    struct_foo g;

    memset(&g, 6, sizeof(g));

    return 0;
}

but it doesn't mean that m_i is going to be equal to 6.


Thursday, March 25, 2004

"The C standard says that NULL is the same as zero." Well, sort of. What it actually says is that what you write (in the source code) as 0 will turn into a null pointer in certain contexts. That *DOES NOT* mean that a null pointer is guaranteed to be represented as all-bits-0. See http://www.eskimo.com/~scs/C-faq/q5.17.html for some examples of machines where memsetting a pointer to 0 would not have given you a null pointer.

The standard is quite careful in how it defines a null pointer. A null pointer is what you get when a "null pointer constant" is used in a context that interprets it as a pointer; converting a null pointer to another pointer type yields a null pointer; null pointers compare equal to each other and unequal to pointers to actual objects or functions. And, well, that's about it.

The specification of the "calloc" function (section 7.14.3.1 in the draft C9x standard, for what it's worth) says "The space is initialized to all bits zero." and has a footnote: "Note that this need not be the same as the representation of floating-point zero or a null pointer constant". I think they slipped up slightly here and meant to say "... or a null pointer"; the null pointer *constant*, as defined earlier in the standard, is a purely syntactic thing. But the point they're making is clear :-).

Gareth McCaughan
Thursday, March 25, 2004

*  Recent Topics

*  Fog Creek Home