By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,369 Members | 1,550 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,369 IT Pros & Developers. It's quick & easy.

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

P: n/a
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.
Jul 22 '05 #1
Share this Question
Share on Google+
17 Replies


P: n/a

<No****@runtime.com> wrote in message
news:fq********************************@4ax.com...
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
Jul 22 '05 #2

P: n/a
On Wed, 22 Sep 2004 03:17:47 -0500, No****@runtime.com 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
Jul 22 '05 #3

P: n/a
> would be wrong. So that is the advantage of the second method, it works in

I meant first method.

john
Jul 22 '05 #4

P: n/a
> 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
Jul 22 '05 #5

P: n/a

"JKop" <NU**@NULL.NULL> wrote in message news:1Z*******************@news.indigo.ie...
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 };

Jul 22 '05 #6

P: n/a
On Wed, 22 Sep 2004 11:02:21 GMT, JKop <NU**@NULL.NULL> 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
Jul 22 '05 #7

P: n/a
> 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
Jul 22 '05 #8

P: n/a
On Wed, 22 Sep 2004 11:02:21 GMT, JKop <NU**@NULL.NULL> 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
Jul 22 '05 #9

P: n/a
> 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
Jul 22 '05 #10

P: n/a
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
Jul 22 '05 #11

P: n/a
"JKop" <NU**@NULL.NULL> wrote in message
news:1Z*******************@news.indigo.ie...
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.
Jul 22 '05 #12

P: n/a
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
Jul 22 '05 #13

P: n/a

"JKop" <NU**@NULL.NULL> wrote in message news:OY*******************@news.indigo.ie...
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.

Jul 22 '05 #14

P: n/a
Ron Natalie posted:

"JKop" <NU**@NULL.NULL> wrote in message
news:OY*******************@news.indigo.ie...
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
Jul 22 '05 #15

P: n/a

"JKop" <NU**@NULL.NULL> wrote in message news:YP*******************@news.indigo.ie...

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.
Jul 22 '05 #16

P: n/a
>> 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
Jul 22 '05 #17

P: n/a
In article <66********************************@4ax.com>,
<No****@runtime.com> 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?
Jul 22 '05 #18

This discussion thread is closed

Replies have been disabled for this discussion.