views:

3854

answers:

7

http://www.fredosaurus.com/notes-cpp/arrayptr/array-initialization.html

1: Page above has a nice list over initialization of arrays.

So 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 ?

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?

A: 

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.

0x6adb015
+15  A: 

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 if you specify at least one.

to set them all to -1, you can use something like std::fill_n

std::fill_n(array, 100, -1);
Evan Teran
That also answered an indirect question about how to fill the array with default values "easily". Thank you.
Milan
+5  A: 

The page you linked states

If an explicit array size is specified, but an shorter initiliazation list is specified, the unspecified elements are set to zero.

Speed issue: Any differences would be negligible for arrays this small. If you work with large arrays and speed is much more important than size, you can have a const array of the default values (initialized at compile time) and then memcpy them to the modifiable array.

laalto
the memcpy isn't a very good idea, since that would be comparable to just setting the values directly speed wise.
Evan Teran
I 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?
Johannes Schaub - litb
Thanks 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)
Milan
The initializer list is done at compile time and loaded at runtime. No need to go copying things around.
Martin York
@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.
laalto
@Martin York: For const arrays, yes. Not for non-const arrays.
laalto
@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.
Johannes Schaub - litb
(Though initializing with -1 is probably better done with memset(..., 0xff), assuming (int32)-1 == 0xffffffff.)
laalto
@laalto: that's assuming 2's compliment, which is not guaranteed.
Evan Teran
@litb: Ah, scope was not mentioned. I was thinking of function scope automatics, not namespace scope statics.
laalto
@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 :)
Johannes Schaub - litb
+1  A: 

1) When you use an initializer, for a struct or an array like that, the unspecified values are essentially default constructed. In the case of a primitive type like ints, that means they will be zeroed. Note that this applies recursively: you could have an array of structs containing arrays and if you specify just the first field of the first struct, then all the rest will be initialized with zeros and default constructors.

2) The compiler will probably generate initializer code that is at least as good as you could do by hand. I tend to prefer to let the compiler do the initialization for me, when possible.

Boojum
1) 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.
Martin York
I 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 :)
Johannes Schaub - litb
@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().
Boojum
@Boojum, he has since removed his comment :)
Johannes Schaub - litb
it could place data into the static data segment, and make "i" refer to it :)
Johannes Schaub - litb
True -- 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.
Boojum
I agree with you :)
Johannes Schaub - litb
+2  A: 

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.

jalf
Good answer. Note that in C++ (not in C) you can do int array[100] = {}; and give the compiler the most freedom :)
Johannes Schaub - litb
agreed, excellent answer. But for a fixed sized array, it'd use std::fill_n :-P.
Evan Teran
fair point, both of you. :)
jalf
+5  A: 

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.

Callum
+1 for finding a cool gcc extension which does what he wants nice and simply.
Evan Teran
i was actually searching for this extension... +1
Warrior
A: 

For the case of an array of single-byte elements, you can use memset to set all elements to the same value.

There's an example here.

Steve Melnikoff