Initialization of all elements of an array to one default value in C++?
Solution 1
Using the syntax that you used,
int array[100] = {-1};
says "set the first element to -1
and the rest to 0
" since all omitted elements are set to 0
.
In C++, to set them all to -1
, you can use something like std::fill_n
(from <algorithm>
):
std::fill_n(array, 100, -1);
In portable C, you have to roll your own loop. There are compiler-extensions or you can depend on implementation-defined behavior as a shortcut if that's acceptable.
Solution 2
There is an extension to the gcc compiler which allows the syntax:
int array[100] = { [0 ... 99] = -1 };
This would set all of the elements to -1.
This is known as "Designated Initializers" see here for further information.
Note this isn't implemented for the gcc c++ compiler.
Solution 3
The page you linked to already gave the answer to the first part:
If an explicit array size is specified, but an shorter initiliazation list is specified, the unspecified elements are set to zero.
There is no built-in way to initialize the entire array to some non-zero value.
As for which is faster, the usual rule applies: "The method that gives the compiler the most freedom is probably faster".
int array[100] = {0};
simply tells the compiler "set these 100 ints to zero", which the compiler can optimize freely.
for (int i = 0; i < 100; ++i){
array[i] = 0;
}
is a lot more specific. It tells the compiler to create an iteration variable i
, it tells it the order in which the elements should be initialized, and so on. Of course, the compiler is likely to optimize that away, but the point is that here you are overspecifying the problem, forcing the compiler to work harder to get to the same result.
Finally, if you want to set the array to a non-zero value, you should (in C++, at least) use std::fill
:
std::fill(array, array+100, 42); // sets every value in the array to 42
Again, you could do the same with an array, but this is more concise, and gives the compiler more freedom. You're just saying that you want the entire array filled with the value 42. You don't say anything about in which order it should be done, or anything else.
Solution 4
C++11 has another (imperfect) option:
std::array<int, 100> a;
a.fill(-1);
Solution 5
With {} you assign the elements as they are declared; the rest is initialized with 0.
If there is no = {}
to initalize, the content is undefined.
Related videos on Youtube
Milan
Updated on August 26, 2021Comments
-
Milan over 2 years
C++ Notes: Array Initialization has a nice list over initialization of arrays. I have a
int array[100] = {-1};
expecting it to be full with -1's but its not, only first value is and the rest are 0's mixed with random values.
The code
int array[100] = {0};
works just fine and sets each element to 0.
What am I missing here.. Can't one initialize it if the value isn't zero ?
And 2: Is the default initialization (as above) faster than the usual loop through the whole array and assign a value or does it do the same thing?
-
Fredrik Widlund about 9 yearsThe behaviour in C and C++ is different. In C {0} is a special case for a struct initializer, however AFAIK not for arrays. int array[100]={0} should be the same as array[100]={[0]=0}, which as a side-effect will zero all other elements. A C compiler should NOT behave as you describe above, instead int array[100]={-1} should set the first element to -1 and the rest to 0 (without noise). In C if you have a struct x array[100], using ={0} as an initializer is NOT valid. You can use {{0}} which will initialize the first element and zero all others, will in most cases will be the same thing.
-
M.M over 8 years@FredrikWidlund It's the same in both languages.
{0}
is not a special case for structs nor arrays. The rule is that elements with no initializer get initialized as if they had0
for an initializer. If there are nested aggregates (e.g.struct x array[100]
) then initializers are applied to the non-aggregates in "row-major" order ; braces may optionally be omitted doing this.struct x array[100] = { 0 }
is valid in C; and valid in C++ so long as the first member ofstruct X
accepts0
as initializer. -
Leushenko about 8 years
{ 0 }
is not special in C, but it's much harder to define a data type that can't be initialized with it since there are no constructors and thus no way to stop0
from being implicitly converted and assigned to something. -
xskxzr almost 6 yearsVoted to reopen because the other question is about C. There are many C++ ways to initialize an array that are not valid in C.
-
Pete almost 5 yearsAlso voted for re-open - C and C++ are different languages
-
RobertS supports Monica Cellio about 4 yearsI removed the C tag since this question is clearly focused on C++ and edited the question´s title accordingly. Now the question can be reopened because it is no longer a duplicate of the illustrated C question. For all of those of you who encounter this question in the future and might want to take a look at the same question for C, here is the link: How to initialize all members of an array to the same value?
-
-
Johannes Schaub - litb almost 15 yearsI don't see the need for the copy and the const array: Why not create the modifiable array in the first place with the pre-filled values?
-
Martin York almost 15 years1) Default initialiszation of POD's is not happening here. Using the list the compiler will generate the values at compile time and place them in a special section of the assembley that is just loaded as part of program initialization (like the code). So the cost is zero at runtime.
-
Milan almost 15 yearsThanks for the speed explanation and how to do it if the speed is an issue with a large array size (which is in my case)
-
Martin York almost 15 yearsThe initializer list is done at compile time and loaded at runtime. No need to go copying things around.
-
Milan almost 15 yearsThat also answered an indirect question about how to fill the array with default values "easily". Thank you.
-
laalto almost 15 years@litb, @Evan: For example gcc generates dynamic initialization (lots of movs) even with optimizations enabled. For large arrays and tight performance requirements, you want to do the init at compile time. memcpy is probably better optimized for large copies than lots of plain movs alone.
-
Johannes Schaub - litb almost 15 yearsGood answer. Note that in C++ (not in C) you can do int array[100] = {}; and give the compiler the most freedom :)
-
laalto almost 15 years@Martin York: For const arrays, yes. Not for non-const arrays.
-
Jason almost 15 yearsagreed, excellent answer. But for a fixed sized array, it'd use std::fill_n :-P.
-
Johannes Schaub - litb almost 15 years@laalto, if it does so, then it's a bug: The compiler, according to the C++ standard, has to apply static initialization to such PODs (int[N]) initialized entirely with constant expressions (-1, ...). I take it you mean int data[] = { 1, 2, 3 }; . Of course, i'm talking about objects having namespace-scope here.
-
laalto almost 15 years(Though initializing with -1 is probably better done with memset(..., 0xff), assuming (int32)-1 == 0xffffffff.)
-
Jason almost 15 years@laalto: that's assuming 2's compliment, which is not guaranteed.
-
Johannes Schaub - litb almost 15 yearsI don't see where he is wrong? int a[100] = { } certainly is initialized to all 0, disregarding to where it appears, and struct { int a; } b[100] = { }; is too. "essentially default constructed" => "value constructed", tho. But this doesn't matter in case of ints, PODS or types with user declared ctors. It only matters for NON-Pods without user declared ctors, to what i know. But i wouldn't cast a down(!) vote because of this. anyway, +1 for you to make it 0 again :)
-
laalto almost 15 years@litb: Ah, scope was not mentioned. I was thinking of function scope automatics, not namespace scope statics.
-
Boojum almost 15 years@Evan: I qualified my statement with "When you use an initializer..." I was not referring to uninitialized values. @Martin: That might work for constant, static, or global data. But I don't see how that would work with something like: int test(){ int i[10]={0}; int v=i[0]; i[0]=5; return v; } The compiler had better be initializing i[] to zeros each time you call test().
-
Johannes Schaub - litb almost 15 yearsit could place data into the static data segment, and make "i" refer to it :)
-
Johannes Schaub - litb almost 15 years@laalto, Oh this makes sense then. After all, it needs a fresh copy each time, in case you modified the array afterwards. Silly me not asking for scope first :)
-
Boojum almost 15 yearsTrue -- technically, in this case it could also elide "i" entirely and just return 0. But using the static data segment for mutable data would be dangerous in multi-threaded environments. The point that I was trying to make in answer to Martin was simply that you can't completely eliminate the cost of initialization. Copy a pre-made chunk from the static data segment, sure, but it's still not free.
-
Matt Joiner over 12 yearsDoes this rule "set the first element to -1 and the rest to 0" also apply to C?
-
Jason over 12 years@MattJoiner: yes, I believe so.
-
chessofnerd almost 11 yearsNote that you will need to add
#include <vector>
to use this solution. -
Jason almost 11 years@chessofnerd: not precisely,
#include <algorithm>
is the right header,<vector>
may or may not include it indirectly, that would depend on your implementation. -
void-pointer almost 11 yearsYou don't have to resort to initializing the array during runtime. If you really need the initialization to happen statically, it's possible to use variadic templates and variadic sequences to generate the desired sequence of
int
s and expand it into the initializer of the array. -
Deqing over 10 yearsI would prefer
int array[100] = {-1, };
otherwise it might confuse people that you are trying to initialize all elements to -1. -
ontherocks over 10 years@Evan Teran I guess the correct syntax to use fill_n for 2D array is
int array2D[3][2]; std::fill_n(&array2D[0][0], 6, -1);
. However, VS2012 gives warning "'std::_Fill_n': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'" -
Jason over 10 years@ontherocks, no there is no correct way to use a single call to
fill_n
to fill an entire 2D array. You need to loop across one dimension, while filling in the other. -
JosephH over 10 yearsAwesome. This syntax also seems to work in clang (so can be used on iOS/Mac OS X).
-
Ben Voigt almost 10 yearsThis is an answer to some other question.
std::fill_n
is not initialization. -
Hertz about 8 yearsYour
non_copyable
type is actually copyable by the means ofoperator=
. -
Abhinav Gauniyal over 7 yearsyou are printing in a loop, why can't you assign in a loop?
-
Dmytro over 7 yearsassigning inside a loop incurs runtime overhead; whereas hardcoding the buffer is free because the buffer is already embedded into the binary, so it doesn't waste time constructing the array from scratch each time the program runs. you are right that printing in a loop isnt a good idea overall though, it's better to append inside the loop and then print once, since each printf call requires a system call, whereas string concatenation using the application's heap/stack does not. Since size in this kind of program is a nonissue, it's best to construct this array at compile time, not runtime.
-
Asu almost 7 years"assigning inside a loop incurs runtime overhead" - You do severely underestimate the optimizer.
-
Asu almost 7 yearsDepending on the size of the array, gcc and clang will "hardcode" or trick the value in, and with larger arrays, directly just
memset
it, even with the "hardcoded" array. -
Steazy about 6 yearsThis is the second worst example of how to use a type I've ever seen...
-
justyy over 4 yearsor
std::fill(begin(a), end(a), -1)
-
hl037_ almost 4 yearsOn some target, the compiler will place a runtime-constructed array in ram, and moreover, you can't declare the array as const. A fill initialization would be actually very nice in such cases...
-
David Stone almost 3 years@Hertz: The explicit defaulting of the move constructor causes the copy and move assignment operators to be implicitly deleted. It doesn't matter for this test case, though, since there are no assignments.
-
Alexis Wilke over 2 yearsNote that the output type in your example (
uint8_t arr = { ...
) is wrong. It's not an array. -
Caleth over 2 years@BenVoigt C++ lacks a succinct way to initialise arrays to anything other than the types default value, and the as-if rule means that a compiler doesn't have to do the zero-initialisation