"memset" vs "= {0}"...Are they equivalent if your initializing variables?

Discussion in 'C++' started by Nollie@runtime.com, Sep 22, 2004.

  1. Guest

    Say you have a struct:

    struct MYSTRUCT
    {
    int x;
    int y;
    int w;
    int h;
    };

    and you want to declare an instance of that struct and initialize it
    to zero. Is "memset" necessary or can i simply initially set it equal
    to {0}.

    Is this:
    MYSTRUCT myStruct = {0};

    the same as this:
    MYSTRUCT myStruct;
    memset(&myStruct, 0, sizeof(MYSTRUCT));

    ?

    The first way seems faster, but I see alot of people doing it the
    second way. Could someone please shed some light on the subject?
    TIA.
     
    , Sep 22, 2004
    #1
    1. Advertising

  2. <> wrote in message
    news:...
    > Say you have a struct:
    >
    > struct MYSTRUCT
    > {
    > int x;
    > int y;
    > int w;
    > int h;
    > };
    >
    > and you want to declare an instance of that struct and initialize it
    > to zero. Is "memset" necessary or can i simply initially set it equal
    > to {0}.
    >
    > Is this:
    > MYSTRUCT myStruct = {0};
    >
    > the same as this:
    > MYSTRUCT myStruct;
    > memset(&myStruct, 0, sizeof(MYSTRUCT));
    >
    > ?
    >
    > The first way seems faster,


    Why do you say it 'seems faster'? The only way to tell if it is faster is to
    time it (or if you are very knowledgable look at the generated machine
    code). Remeber compilers are usually pretty code at optimising code, I would
    certainly hope that the two methods would be exactly the same on a good
    compiler (but I haven't actually checked this).

    > but I see alot of people doing it the
    > second way. Could someone please shed some light on the subject?


    The two ways are the same for the struct you have declared. But if you had a
    struct with members that had a constructor (e.g. a std::string) then memset
    would be wrong. So that is the advantage of the second method, it works in
    more situations and you could reasonable hope to get a compiler error
    message if you used it incorrectly.

    > TIA.


    john
     
    John Harrison, Sep 22, 2004
    #2
    1. Advertising

  3. Tom Widmer Guest

    On Wed, 22 Sep 2004 03:17:47 -0500, wrote:

    >Say you have a struct:
    >
    >struct MYSTRUCT
    >{
    > int x;
    > int y;
    > int w;
    > int h;
    >};
    >
    >and you want to declare an instance of that struct and initialize it
    >to zero. Is "memset" necessary or can i simply initially set it equal
    >to {0}.
    >
    >Is this:
    >MYSTRUCT myStruct = {0};
    >
    >the same as this:
    >MYSTRUCT myStruct;
    >memset(&myStruct, 0, sizeof(MYSTRUCT));
    >
    >?
    >
    >The first way seems faster, but I see alot of people doing it the
    >second way. Could someone please shed some light on the subject?


    The first way is generally better, since it zero initializes all
    members. Memsetting to 0 is not always the same as zero initializing,
    particularly for floating point and pointer members, which may have 0
    values that aren't all bits zero.

    Performance wise, I don't know which would be faster, you'd have to
    measure it.

    Tom
     
    Tom Widmer, Sep 22, 2004
    #3
  4. > would be wrong. So that is the advantage of the second method, it works in

    I meant first method.

    john
     
    John Harrison, Sep 22, 2004
    #4
  5. JKop Guest

    > struct MYSTRUCT
    > {
    > int x;
    > int y;
    > int w;
    > int h;
    > };
    >


    > MYSTRUCT myStruct = {0};


    All this does is set "myStruct.x" to 0, all the others
    still contain no particular value.


    > MYSTRUCT myStruct;
    > memset(&myStruct, 0, sizeof(MYSTRUCT));


    This is the Microsoft way of doing things.

    In fact, they've even made a... uh... macro... out of it
    called "ZeroMemory" which you use like so:

    ZeroMemory(&myStruct, sizeof(MYSTRUCT));

    Don't use the Microsoft way. It's non-portable, plus it
    screws things up when you have the likes of:

    struct Blah
    {
    int k;
    std::string p;
    };

    Instead, do the following:

    struct Blah
    {
    int x;
    int y;
    int w;
    int h;
    std::string r;
    };

    Blah poo = Blah();

    This gives all member variables their default value, which
    for the intrinsic types is 0, for pointer is the null
    pointer value which may or may not be represented by 0
    (memset is unaware of this and as such can screw things
    up), and for classes it calls their default constructor
    with no arguments.


    Blah poo = Blah();

    is superiour in every way and is fully portable. Use it!


    -JKop
     
    JKop, Sep 22, 2004
    #5
  6. Ron Natalie Guest

    "JKop" <> wrote in message news:1Zc4d.31715$...

    > All this does is set "myStruct.x" to 0, all the others
    > still contain no particular value.


    Wrong answer....When you omit terms in an aggregate initializer the rest
    are default initialized.

    >
    > Instead, do the following:
    >
    > struct Blah
    > {
    > int x;
    > int y;
    > int w;
    > int h;
    > std::string r;
    > };
    >
    > Blah poo = Blah();
    >

    So would
    Blah poo = { 0 };
     
    Ron Natalie, Sep 22, 2004
    #6
  7. Tom Widmer Guest

    On Wed, 22 Sep 2004 11:02:21 GMT, JKop <> wrote:

    >> struct MYSTRUCT
    >> {
    >> int x;
    >> int y;
    >> int w;
    >> int h;
    >> };
    >>

    >
    >> MYSTRUCT myStruct = {0};

    >
    >All this does is set "myStruct.x" to 0, all the others
    >still contain no particular value.


    Nope, remaining members are value-initialized, which for built-ins
    means initialized to 0. You can also do:

    MYSTRUCT myStruct = {};

    to get the same effect.

    Tom
     
    Tom Widmer, Sep 22, 2004
    #7
  8. JKop Guest

    > MYSTRUCT myStruct = {};


    Cool! Didn't know that.

    The only advantage

    MYSTRUCT myStruct = MYSTRUCT();

    would have over it thought is that it can be used for *any*
    type, as opposed to just for arrays and POD's. My proposal
    would be especially preferable for use in a template.

    -JKop
     
    JKop, Sep 22, 2004
    #8
  9. Guest

    On Wed, 22 Sep 2004 11:02:21 GMT, JKop <> wrote:

    >struct Blah
    >{
    > int x;
    > int y;
    > int w;
    > int h;
    > std::string r;
    >};
    >
    >Blah poo = Blah();
    >
    >This gives all member variables their default value, which
    >for the intrinsic types is 0, for pointer is the null
    >pointer value which may or may not be represented by 0
    >(memset is unaware of this and as such can screw things
    >up), and for classes it calls their default constructor
    >with no arguments.
    >
    >
    >Blah poo = Blah();
    >
    >is superiour in every way and is fully portable. Use it!
    >
    >
    >-JKop
    >


    Not necessarily. Of the three methods I've tested, Blah()
    appears to be the slowest.

    The method:

    Blah poo;
    memset(&poo, 0, sizeof(Blah));

    is the fastest, and

    Blah poo = {0}

    is a very close second;

    Basically, you must compromise speed for safety and portability.

    This is first time I've ever timed functions. I'm Visual Studio.NET
    2003, SDK, WindowsXP.

    My timing algorithm:
    LARGE_INTEGER start;
    LARGE_INTEGER end;
    QueryPerformanceCounter( &start );
    ....Do Something
    QueryPerformanceCounter( &end );
    TRACE( TEXT( "Time = %d\n" ), end.QuadPart-start.QuadPart );

    Granted, we're talking minimal differences, but that's besides the
    point.

    Please explain a little deeper as to why memset might not set a
    pointer or a floating point number to zero. It does on my computer.

    -Nollie
     
    , Sep 22, 2004
    #9
  10. JKop Guest

    > Not necessarily. Of the three methods I've tested, Blah()
    > appears to be the slowest.
    >
    > The method:
    >
    > Blah poo;
    > memset(&poo, 0, sizeof(Blah));
    >
    > is the fastest, and
    >
    > Blah poo = {0}
    >
    > is a very close second;
    >
    > Basically, you must compromise speed for safety and portability.
    >
    > This is first time I've ever timed functions. I'm Visual Studio.NET
    > 2003, SDK, WindowsXP.
    >
    > My timing algorithm:
    > LARGE_INTEGER start;
    > LARGE_INTEGER end;
    > QueryPerformanceCounter( &start );
    > ...Do Something
    > QueryPerformanceCounter( &end );
    > TRACE( TEXT( "Time = %d\n" ), end.QuadPart-start.QuadPart );
    >
    > Granted, we're talking minimal differences, but that's besides the
    > point.
    >
    > Please explain a little deeper as to why memset might not set a
    > pointer or a floating point number to zero. It does on my computer.
    >
    > -Nollie


    Sometimes it takes me 10mins 23secs to get to the bustop. Sometimes it takes
    9mins 58secs...

    I wouldn't use "QueryPerformanceCounter" as an indicator for this, unless
    you time it a few thousand times and get the average, but even still, I'm
    not sure how accurate it'd be.

    As regards pointers... well let's say that on a certain system, a pointer
    variable takes up 32 bits in memory, as so:


    0000 0000 0000 0000 0000 0000 0000 0000


    What you're looking at above is "all bits zero". On Windows, this indicates
    that the pointer is a null pointer. Now imagine a system where the memory
    address 0 is a valid one, ie. it's the first byte of memory, and that on
    this particular system, the null pointer value is:

    1111 1111 1111 1111 1111 1111 1111 1111


    When you write a program with the following line in it:


    int* p_k = 0;

    The compiler doesn't produce code that sets all bits to zero... no no...
    what it does is produce code that sets it to the null pointer value for that
    system (and/or for that type, I believe systems may choose to have different
    null pointer values depending on the type...). But "memset" doesn't have a
    clue about this, all it does is set all bits to zero, which may be a valid
    memory address on some systems, hence it's not portable.

    And as regards floating point numbers, implementations aren't obligated to
    represent the value zero as "all bits zero" either.

    I don't see how either of the three could be slower/faster than each other,
    they should all yield the same machine code (except maybe the call to
    "memeset" might add overhead if it's not inline...)


    -JKop
     
    JKop, Sep 22, 2004
    #10
  11. JKop Guest

    JKop posted:

    >> Not necessarily. Of the three methods I've tested, Blah

    ()
    >> appears to be the slowest.
    >>
    >> The method:
    >>
    >> Blah poo;
    >> memset(&poo, 0, sizeof(Blah));
    >>
    >> is the fastest, and
    >>
    >> Blah poo = {0}
    >>
    >> is a very close second;
    >>
    >> Basically, you must compromise speed for safety and

    portability.
    >>
    >> This is first time I've ever timed functions. I'm

    Visual Studio.NET
    >> 2003, SDK, WindowsXP.
    >>
    >> My timing algorithm:
    >> LARGE_INTEGER start;
    >> LARGE_INTEGER end;
    >> QueryPerformanceCounter( &start );
    >> ...Do Something
    >> QueryPerformanceCounter( &end );
    >> TRACE( TEXT( "Time = %d\n" ), end.QuadPart-

    start.QuadPart );
    >>
    >> Granted, we're talking minimal differences, but that's

    besides the
    >> point.
    >>
    >> Please explain a little deeper as to why memset might

    not set a
    >> pointer or a floating point number to zero. It does on

    my computer.
    >>
    >> -Nollie

    >
    > Sometimes it takes me 10mins 23secs to get to the bustop.

    Sometimes it
    > takes 9mins 58secs...
    >
    > I wouldn't use "QueryPerformanceCounter" as an indicator

    for this,
    > unless you time it a few thousand times and get the

    average, but even
    > still, I'm not sure how accurate it'd be.
    >
    > As regards pointers... well let's say that on a certain

    system, a
    > pointer variable takes up 32 bits in memory, as so:
    >
    >
    > 0000 0000 0000 0000 0000 0000 0000 0000
    >
    >
    > What you're looking at above is "all bits zero". On

    Windows, this
    > indicates that the pointer is a null pointer. Now imagine

    a system
    > where the memory address 0 is a valid one, ie. it's the

    first byte of
    > memory, and that on this particular system, the null

    pointer value is:
    >
    > 1111 1111 1111 1111 1111 1111 1111 1111
    >
    >
    > When you write a program with the following line in it:
    >
    >
    > int* p_k = 0;
    >
    > The compiler doesn't produce code that sets all bits to

    zero... no
    > no... what it does is produce code that sets it to the

    null pointer
    > value for that system (and/or for that type, I believe

    systems may
    > choose to have different null pointer values depending on

    the type...).
    > But "memset" doesn't have a clue about this, all it does

    is set all
    > bits to zero, which may be a valid memory address on some

    systems,
    > hence it's not portable.
    >
    > And as regards floating point numbers, implementations

    aren't obligated
    > to represent the value zero as "all bits zero" either.
    >
    > I don't see how either of the three could be

    slower/faster than each
    > other, they should all yield the same machine code

    (except maybe the
    > call to "memeset" might add overhead if it's not

    inline...)
    >
    >
    > -JKop


    And I hope you realize what havoc "memset" would cause with
    a non-POD type...

    -JKop
     
    JKop, Sep 22, 2004
    #11
  12. "JKop" <> wrote in message
    news:1Zc4d.31715$...

    >> struct MYSTRUCT
    >> {
    >> int x;
    >> int y;
    >> int w;
    >> int h;
    >> };
    >>

    >
    >> MYSTRUCT myStruct = {0};

    >
    > All this does is set "myStruct.x" to 0, all the others
    > still contain no particular value.


    I think not. If you brace-initialize any elements of an aggregate, the ones
    you don't mention get set to zero.

    So, for example:

    int x[5] = { 42 };

    and

    int x[5] = { 42, 0, 0, 0, 0 };

    are equivalent.
     
    Andrew Koenig, Sep 22, 2004
    #12
  13. JKop Guest

    One thing I forgot to mention:

    When you do "memset", padding bits (if any) get altered
    too. I'm not sure if the Standard allows this...


    -JKop
     
    JKop, Sep 22, 2004
    #13
  14. Ron Natalie Guest

    "JKop" <> wrote in message news:OYf4d.31743$...
    > One thing I forgot to mention:
    >
    > When you do "memset", padding bits (if any) get altered
    > too. I'm not sure if the Standard allows this...
    >

    Allows what? You are allowed to access them, yes their state
    is undefined during normal assignment/initialization.
     
    Ron Natalie, Sep 22, 2004
    #14
  15. JKop Guest

    Ron Natalie posted:

    >
    > "JKop" <> wrote in message
    > news:OYf4d.31743$...
    >> One thing I forgot to mention:
    >>
    >> When you do "memset", padding bits (if any) get altered
    >> too. I'm not sure if the Standard allows this...
    >>

    > Allows what? You are allowed to access them, yes their

    state
    > is undefined during normal assignment/initialization.
    >
    >


    I'm not sure if the Standard allows you to access the
    padding bits.

    For instance, if you have:

    struct Blah
    {
    int a;
    char b;
    char c;
    char d;
    int b;
    };


    Chances are that it will be lain out in memory as so:

    | a | b | c | padding | d


    You can access the object as follows:

    poo.a
    poo.b
    poo.c
    poo.d

    And a copy constructor and a assignment operator will both
    copy the four member variables, but I'm not sure if the
    Standard gives us control over the padding bits... anyone
    know? I recall looking in the Standard for this before and
    finding nothing.

    Let's say hypothetically speaking that you *can't* mess
    with padding bits. A certain implementation, when you do
    the following:

    Blah poo;
    char x;

    Might stick "x" into memory as so:

    | a | b | c | x | d |


    Again, I stress *hypothetically speaking*.

    So does anyone know if the Standard allows messing with
    padding?


    -JKop




    -JKop
     
    JKop, Sep 22, 2004
    #15
  16. Ron Natalie Guest

    "JKop" <> wrote in message news:YPh4d.31764$...
    >
    > I'm not sure if the Standard allows you to access the
    > padding bits.


    Read the last paragraph of 3.10 of the standard.

    > And a copy constructor and a assignment operator will both
    > copy the four member variables, but I'm not sure if the
    > Standard gives us control over the padding bits... anyone
    > know? I recall looking in the Standard for this before and
    > finding nothing.


    The standard doesn't specify any behavior as to what happens to the
    pad bytes in assignment or construction.

    > So does anyone know if the Standard allows messing with
    > padding?
    >

    If you mean aliasing it to char* and then accessing the chars, it is allowed.
     
    Ron Natalie, Sep 22, 2004
    #16
  17. JKop Guest

    >> I'm not sure if the Standard allows you to access the padding bits.
    >
    > Read the last paragraph of 3.10 of the standard.


    <QUOTE>
    15 If a program attempts to access the stored value of an object through an
    lvalue of other than one of the following
    types the behavior is undefined48):
    — the dynamic type of the object,
    — a cv-qualified version of the dynamic type of the object,
    — a type that is the signed or unsigned type corresponding to the dynamic
    type of the object,
    — a type that is the signed or unsigned type corresponding to a cv-qualified
    version of the dynamic type of
    the object,
    — an aggregate or union type that includes one of the aforementioned types
    among its members (including,
    recursively, a member of a subaggregate or contained union),
    — a type that is a (possibly cv-qualified) base class type of the dynamic
    type of the object,
    — a char or unsigned char type.
    </QUOTE>


    Hmmm... I suppose.


    Anyone?


    -JKop
     
    JKop, Sep 22, 2004
    #17
  18. Greg Comeau Guest

    In article <>,
    <> wrote:
    >Please explain a little deeper as to why memset might not set a
    >pointer or a floating point number to zero. It does on my computer.


    Because all bits zero is not a valid representation for
    floating points or pointers on many platforms.
    --
    Greg Comeau / Comeau C++ 4.3.3, for C++03 core language support
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
     
    Greg Comeau, Sep 22, 2004
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest
    Replies:
    0
    Views:
    401
    Guest
    Sep 23, 2004
  2. Guest
    Replies:
    1
    Views:
    435
    Ron Natalie
    Sep 23, 2004
  3. Asfand Yar Qazi
    Replies:
    4
    Views:
    410
    Asfand Yar Qazi
    Nov 12, 2004
  4. Martin M.
    Replies:
    4
    Views:
    350
    Simon Brunning
    Dec 15, 2005
  5. Dave Rudolf
    Replies:
    1
    Views:
    308
    Kai-Uwe Bux
    May 17, 2006
Loading...

Share This Page