views:

540

answers:

7

Hi

How do I automatically set a dynamically allocated array of floats to zero(0.0) during allocation

Is this OK

float* delay_line = new float[filter_len];

//THIS
memset(delay_line, 0.0, filter_len); //can I do this for a float??

//OR THIS
for (int i = 0; i < filter_len; i++)
  delay_line[i] = 0.0;

Which is the most efficient way

Thanks

+8  A: 

use

#include <algorithm>
...
std::fill_n( delay_line, filer_len, 0 )
xtofl
If not you cannot use a vector, this is the most type-safe, modern c++ way to do it. memset might be faster, but it just zeros bytes with no type-checking, if you get your math wrong you are in trouble.
iain
I agree on fill_n being the preferred method, even if it's slightly slower (and I'll only believe that when I see it ;) As opposed to memset, this method is both type safe and much easier 'extensible/adaptable' (you can use this method to initialize to e.g. 4.2 too)
Pieter
+12  A: 

Use sizeof(float) * filter_len unless you are working in some odd implementation where sizeof(float) == sizeof(char).

memset(delay_line, 0, sizeof(float) * filter_len);

Edit: As Stephan202 points out in the comments, 0.0 is a particularly easy floating point value to code for memset since the IEEE standard representation for 0.0 is all zero bits.

memset is operating in the realm of memory, not the realm of numbers. The second parameter, declared an int, is cast to an unsigned char. If your implementation of C++ uses four bytes per float, the following relationships hold:

  • If you memset the float with 0, the value will be 0.0.
  • If you memset the float with 1, the value will be 2.36943e-38.
  • If you memset the float with 42, the value will be 1.51137e-13.
  • If you memset the float with 64, the value will be 3.00392.

So zero is a special case.

If this seems peculiar, recall that memset is declared in <cstring> or <string.h>, and is often used for making things like "***************" or "------------------". That it can also be used to zero memory is a nifty side-effect.

As Milan Babuškov points out in the comments, there is a function bzero (nonstandard and deprecated), available for the moment on Mac and Linux but not Microsoft, which, because it is specially tailored to setting memory to zero, safely omits a few instructions. If you use it, and a puritanical future release of your compiler omits it, it is trivial to implement bzero yourself in a local compatibility patch, unless the future release has re-used the name for some other purpose.

Thomas L Holaday
Thanks, will this set each value in delay_line to 0.0?
+1, correct choice. memset() is the fastest way.
Yes, this will set each value to 0.0: if sign, exponent and fraction are 0, then the float represents 0.0: http://en.wikipedia.org/wiki/IEEE_754-1985
Stephan202
IEEE 754 is completely unrelated to C++ standard. There is nothing in C++ standard that says implementations must follow IEEE 754.
Milan Babuškov
Also, if you go down this path, bzero should be faster than memset:http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown/
Milan Babuškov
@Milan: Agreed, bzero is more expressive of programmer intent. Looking at the implementations of bzero.c and memset.c in glibc, bzero is able to dispense with a few |= operations because it does not need to deal with the case of someone passing 268435521 because he wants 'A'. bzero isn't standard C, alas.
Thomas L Holaday
+3  A: 

Now that we're at it: even better would be to use the vector class.

std::vector< float > delay_line( filter_len, 0.0 );
xtofl
But take a look at Neil's answer: you won't need the 0.0 argument: this is the default initialization argument value.
xtofl
+11  A: 

Use a std::vector instead:

std::vector<float> delay_line( filter_len );

The vector will be zero initialised.

anon
Not the most efficient way, but surely the most elegant.
Dave Van den Eynde
It's the most efficient in terms of programmer effort (no need to manage destruction) and that is normally the most important thing to optimise.
anon
There is no need to manage destruction or construction for an array on the stack :-)
Thomas L Holaday
The most efficient way in terms of programmer effort is to get the manager to mark the request which requires the zeroed float array "WONT FIX".
Thomas L Holaday
Thomas, you should put that in your resume: "experience with avoiding to fix things"
Dave Van den Eynde
+1  A: 

Which is the most efficient way

memset maybe a tad faster, BUT WHO CARES!?!? Micro-optimization down to this level is a total waste of time, unless you're programming a calculator, and probably not even then.

I think the memset way is clearer, BUT I think you really had better check your man-pages for memset... I'd be suprised if your version of standard libraries has a memset function which takes a float as the second argument.

PS: The bit pattern representing zero is the same for both integers and floats... this is by design, not just good luck.

Good Luck ;-)

Cheers. Keith.

corlettk
Bashing micro-optimization is a total waste of time. If the QS didn't need optimization, why would he ask which is the most efficient way?
Dave Van den Eynde
I prefer memset but was unsure if binary representation of a floating point zero is the same as integer zeroThanks for clearing that up
A: 

The elements of a dynamically allocated array can be initialized to the default value of the element type by following the array size by an empty pair of parentheses:

float* delay_line = new float[filter_len]();
Bruno Martinez
+1  A: 

Another option is to use calloc to allocate and zero at the same time:

float *delay_line = (float *)calloc(sizeof(float), filter_len);

The advantage here is that, depending on your malloc implementation, it may be possible to avoid zeroing the array if it's known to be allocated from memory that's already zeroed (as pages allocated from the operating system often are)

Keep in mind that you must use free() rather than delete [] on such an array.

bdonlan