is it safe to zero float array with memset?

  • Thread starter 69dbb24b2db3daad932c457cccfd6
  • Start date
6

69dbb24b2db3daad932c457cccfd6

Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Zhang Le
 
R

Robert Gamble

Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Is the memory for the array dynamically allocated? If not, you could
do this:
float a[len] = {0};

Using memset to set a value to zero is only safe on integer types, not
floating point types or pointers.

Robert Gamble
 
S

Sensei

Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Zhang Le

It depends. If it's an array of float yes, of it's an array of float*
you're setting all ptrs to NULL, safe anyway.
 
F

Flash Gordon

Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

No, it's not safe. All bits zero may not represent a floating point 0.0
and could be a trap representation.
 
R

Robert Gamble

Sensei said:
It depends. If it's an array of float yes, of it's an array of float*
you're setting all ptrs to NULL, safe anyway.

You are making little sense. You said it depends, then you go on to
say that it is safe in either case? Well, you are wrong on all counts.
In either case there is no guarantee made by the C Standard that
either of these scenerios is safe. NULL need not be all-bits zero,
neither does float need to use this as a representation for zero (or
anything else for that matter).

Robert Gamble
 
6

69dbb24b2db3daad932c457cccfd6

Thanks for the reply, I now think it's unsafe to use memset.

Interestingly, from FAQ 5.17:
http://www.eskimo.com/~scs/C-faq/s5.html

I find there are some cases where NULL is not zero, which means the
only portable way to test a pointer aginst NULL is via:
if (p != NULL) {...}
if (p == NULL) {...}

And if (p), if (!p) will fail on these systems if I understand
correctly. Horrible things will happy consider how many of us write
code this way,.

Zhang Le
 
D

David Resnick

Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Zhang Le

Search comp.lang.c for "float all bits 0" and you'll find nice large
discussions on this.

It may be that you can still be portable and use memset, for example
you could have a function that is like below (not checked)

void clear_array(double *array, size_t size)
{
/* following define is C99, but you may find others on
other implementations. Or define other conditions under
which you want to use memset */
#if defined(__STDC_IEC_559__)
memset(array, 0, size * sizeof(double)
#else
size_t i;

for (i = 0; i < size; i++) {
array = 0.0;
}
#endif
}

It would only do the memset if IEEE754 math is used. In that
case, as I understand it, all bits 0 is 0. You might be able
to get other indicators that memset is to be used as well.

-David
 
6

69dbb24b2db3daad932c457cccfd6

Sorry for my last post. Again from FAQ 5.3 I found both if (p) and if
(!p) are correct regardless of the value of NULL.

Zhang Le
 
K

Kenneth Brody

Thanks for the reply, I now think it's unsafe to use memset.

Interestingly, from FAQ 5.17:
http://www.eskimo.com/~scs/C-faq/s5.html

I find there are some cases where NULL is not zero, which means the
only portable way to test a pointer aginst NULL is via:
if (p != NULL) {...}
if (p == NULL) {...}

And if (p), if (!p) will fail on these systems if I understand
correctly. Horrible things will happy consider how many of us write
code this way,.

My understanding (and I'm sure someone who knows the standard better
than, I will correct me if I'm wrong) is that NULL compares to zero
even on platforms where NULL is not all-bits-zero.

Therefore, "if (p)" is the same as "if (p != NULL)" even on not-all-
bits-zero platforms.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
S

Sensei

You are making little sense. You said it depends, then you go on to
say that it is safe in either case? Well, you are wrong on all counts.

I always memset-ed before any use! :)

In either case there is no guarantee made by the C Standard that
either of these scenerios is safe. NULL need not be all-bits zero,
neither does float need to use this as a representation for zero (or
anything else for that matter).

Safety in my opinion is not memory I don't have rights to access.
Making a zero-bit float or ptr must be safe as long as the memory is
accessible. Isn't it? For this matter, setting all bytes to any value
(even random) is safe. Not meaningful, but safe.
 
K

Keith Thompson

I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

It's possible, but rare, for all-bits-zero not to be the
representation of a floating-point 0.0.

Here's an approach that might be useful if you're concerned about both
maximal portability and good performance:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static int float_zero_is_all_bits_zero(void)
{
float f = 0.0;
unsigned char zero_bytes[sizeof f] = { 0 };
return memcmp(&f, zero_bytes, sizeof f) == 0;
}

void set_float_zero(float *dest, size_t count)
{
static int initialized = 0;
int may_use_memset;

if (!initialized) {
may_use_memset = float_zero_is_all_bits_zero();
initialized = 1;
}

if (may_use_memset) {
memset(dest, 0, count * sizeof *dest);
}
else {
size_t i;
for (i = 0; i < count; i ++) {
dest = 0.0;
}
}
}

#define ARR_LEN 1000

int main(void)
{
float *arr = malloc(ARR_LEN * sizeof *arr);
set_float_zero(arr, ARR_LEN);
return 0;
}

The first call to set_float_zero() will invoke
float_zero_is_all_bits_zero() to determine how 0.0 is actually
represented; it then uses memset() if it's safe, and falls back to an
explicit loop if it isn't. On calls after the first, it merely checks
a single flag.

This is useful if the memset() is significantly faster than the
explicit loop, something that is not at all obvious. If you're
concerned about performance, you should measure the actual performance
of both techniques. A sufficiently clever compiler might even
transform the loop to the equivalent of a memset() call -- or even
something faster, since it knows that the array is aligned.

Interestingly, the compiler I tried (gcc 3.4.4) warned that
"`may_use_memset' might be used uninitialized in this function". In
fact, the use of the "initialized" variable guarantees that this won't
happen, but the compiler wasn't able to figure this out. You can
always inhibit the warning by initializing may_use_memset.
 
G

Gordon Burditt

It depends. If it's an array of float yes, of it's an array of float*
I always memset-ed before any use! :)



Safety in my opinion is not memory I don't have rights to access.
Making a zero-bit float or ptr must be safe as long as the memory is
accessible. Isn't it?

Not necessarily if you use the results afterward *as floats* or *as
pointers to float*.
For this matter, setting all bytes to any value
(even random) is safe. Not meaningful, but safe.

Not if you then try to use the value as a float or as a pointer.
Whatever bit pattern you set a float to might be a trapping NaN.
A pointer might compare unequal to NULL and then smegfault when you
try to dereference it, or it might even cause an exception when you
load it into an address register (no dereference needed).

Gordon L. Burditt
 
D

Dave Vandervies

Keith Thompson said:
void set_float_zero(float *dest, size_t count)
{
static int initialized = 0;
int may_use_memset;

if (!initialized) {
may_use_memset = float_zero_is_all_bits_zero();
initialized = 1;
}
[snip]

Interestingly, the compiler I tried (gcc 3.4.4) warned that
"`may_use_memset' might be used uninitialized in this function". In
fact, the use of the "initialized" variable guarantees that this won't
happen, but the compiler wasn't able to figure this out. You can
always inhibit the warning by initializing may_use_memset.

Does the warning go away if you make may_use_memset static?


dave
 
R

Richard Heathfield

Kenneth said:
My understanding (and I'm sure someone who knows the standard better
than, I will correct me if I'm wrong) is that NULL compares to zero
even on platforms where NULL is not all-bits-zero.

Therefore, "if (p)" is the same as "if (p != NULL)" even on not-all-
bits-zero platforms.

Just to help you sleep well tonight, I can assure you that you are 100%
correct, which makes a change around here. (I've just been reading today's
feed, and what a sorry collection of articles it is.)
 
L

Lawrence Kirby

On Fri, 22 Jul 2005 15:13:49 -0500, Sensei wrote:

....
Safety in my opinion is not memory I don't have rights to access.
Making a zero-bit float or ptr must be safe as long as the memory is
accessible. Isn't it? For this matter, setting all bytes to any value
(even random) is safe. Not meaningful, but safe.

Setting the bits can be done safely. Reading the value as a float or
pointer variable later is not, that can have undefined behaviour if you
happened to set a trap representation which can be as unsafe as bad memory
accesses.

Lawrence
 
M

Malcolm

I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?
No, but it's "safe enough". If you do need the speed increment, it is
probably worth the small risk that someone will run your code on a system
that doesn't use all bits zero for float 0.0.
 
K

Keith Thompson

Malcolm said:
No, but it's "safe enough". If you do need the speed increment, it is
probably worth the small risk that someone will run your code on a system
that doesn't use all bits zero for float 0.0.

I don't *quite* agree that it's "safe enough".

If I were going to use memset() to zero an array of floats, the first
thing I'd do is measure the performance to see if memset() really is
faster. If it isn't, there's no point in using anything other than an
explicit loop, which is known to be safe.

If I found that memset() really is faster, *and* that the increase in
performance is actually significant, I'd probably write a test
function, to be invoked once at program startup, that checks whether
0.0 really is all-bits-zero. If it isn't, it would abort the program.
If the program is eventually ported to a system were 0.0 *isn't*
all-bits-zero, it will then abort immediately rather than running
and giving mysteriously incorrect results.

If even invoking the test function once is a problem, I'd move the
test into the build procedure, so the program won't even build unless
it's first proven that 0.0 is all-bits-zero.

For that matter, as long as I'm messing with the build procedure, I
might as well have it set a macro that indicates whether memset() is
safe, and use that in the code to determine at compilation time which
method to use.

The only problem with this is that it's difficult to find a platform
on which 0.0 *isn't* all-bits-zero, so any code that assumes it isn't
may not be tested properly.
 
S

Sensei

Not necessarily if you use the results afterward *as floats* or *as
pointers to float*.

Not if you then try to use the value as a float or as a pointer.
Whatever bit pattern you set a float to might be a trapping NaN.
A pointer might compare unequal to NULL and then smegfault when you
try to dereference it, or it might even cause an exception when you
load it into an address register (no dereference needed).


Well, yes and no. I mean, when I was using DOS (more than a decade
ago), an important pointer was the one at the interrupt vector table,
or the video memory (0x0000 and 0xA000 if I remember), and it was
always done by setting a ptr to a number. Resetting the IVT by
memsetting, was dangerous, but if you wanted to do some tricks, it was
a possible choice.

The meaning of what it contains, should be of no concern for C, as it's
a matter of the implementation itself.

Whether you're accessing a non-readable memory by deferencing a weird
ptr, it's again the implementation, but setting the ptr still results
in a safe operation. Writing and even reading to that location is,
naturally, not safe.

For floats, again, NaN may be a result of a misinterpretation of what
the float was meant to be, but it cannot be considered unsafe from C
point of view.

It's the programmer who must be sure of all the meanings :)
 
S

Sensei

Setting the bits can be done safely. Reading the value as a float or
pointer variable later is not, that can have undefined behaviour if you
happened to set a trap representation which can be as unsafe as bad memory
accesses.

Lawrence

Yes, it really depends on what those pointers and floats mean.
 
E

Eric Sosman

Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Yes, it is safe. Not one hundred percent safe, but safer
than riding in an automobile, say, or eating home-cooked food.

Here's the bigger question: Why do you care? Frankly, if
your program spends a significant amount of its running time
setting things to zero (as opposed to filling them with Useful
Information), there is probably something wrong with the design
of your program. In four decades of programming, I have run
into only ONE situation where the speed of zeroing memory was
important -- and I will bet dollars to doughnuts that your
program is not (or should not be) Case Number Two.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,044
Latest member
RonaldNen

Latest Threads

Top