Assuming that we have a T myarray[100]
with T = int, unsigned int, long long int or unsigned long long int, what is the fastest way to reset all its content to
You can use memset
, but only because our selection of types is restricted to integral types.
In general case in C it makes sense to implement a macro
#define ZERO_ANY(T, a, n) do{\
T *a_ = (a);\
size_t n_ = (n);\
for (; n_ > 0; --n_, ++a_)\
*a_ = (T) { 0 };\
} while (0)
This will give you C++-like functionality that will let you to "reset to zeros" an array of objects of any type without having to resort to hacks like memset
. Basically, this is a C analog of C++ function template, except that you have to specify the type argument explicitly.
On top of that you can build a "template" for non-decayed arrays
#define ARRAY_SIZE(a) (sizeof (a) / sizeof *(a))
#define ZERO_ANY_A(T, a) ZERO_ANY(T, (a), ARRAY_SIZE(a))
In your example it would be applied as
int a[100];
ZERO_ANY(int, a, 100);
// or
ZERO_ANY_A(int, a);
It is also worth noting that specifically for objects of scalar types one can implement a type-independent macro
#define ZERO(a, n) do{\
size_t i_ = 0, n_ = (n);\
for (; i_ < n_; ++i_)\
(a)[i_] = 0;\
} while (0)
and
#define ZERO_A(a) ZERO((a), ARRAY_SIZE(a))
turning the above example into
int a[100];
ZERO(a, 100);
// or
ZERO_A(a);
memset
(from <string.h>
) is probably the fastest standard way, since it's usually a routine written directly in assembly and optimized by hand.
memset(myarray, 0, sizeof(myarray)); // for automatically-allocated arrays
memset(myarray, 0, N*sizeof(*myarray)); // for heap-allocated arrays, where N is the number of elements
By the way, in C++ the idiomatic way would be to use std::fill
(from <algorithm>
):
std::fill(myarray, myarray+N, 0);
which may be optimized automatically into a memset
; I'm quite sure that it will work as fast as memset
for int
s, while it may perform slightly worse for smaller types if the optimizer isn't smart enough. Still, when in doubt, profile.
zero(myarray);
is all you need in C++.
Just add this to a header:
template<typename T, size_t SIZE> inline void zero(T(&arr)[SIZE]){
memset(arr, 0, SIZE*sizeof(T));
}
From memset():
memset(myarray, 0, sizeof(myarray));
You can use sizeof(myarray)
if the size of myarray
is known at compile-time. Otherwise, if you are using a dynamically-sized array, such as obtained via malloc
or new
, you will need to keep track of the length.
For static declaration I think you could use:
T myarray[100] = {0};
For dynamic declaration I suggest the same way: memset
Here's the function I use:
template<typename T>
static void setValue(T arr[], size_t length, const T& val)
{
std::fill(arr, arr + length, val);
}
template<typename T, size_t N>
static void setValue(T (&arr)[N], const T& val)
{
std::fill(arr, arr + N, val);
}
You can call it like this:
//fixed arrays
int a[10];
setValue(a, 0);
//dynamic arrays
int *d = new int[length];
setValue(d, length, 0);
Above is more C++11 way than using memset. Also you get compile time error if you use dynamic array with specifying the size.