31

I'm trying to initialize an int array with everything set at -1.

I tried the following, but it doesn't work. It only sets the first value at -1.

int directory[100] = {-1};

Why doesn't it work right?

neuromancer
  • 53,769
  • 78
  • 166
  • 223
  • 4
    In GCC and clang you can, as a [GNU C extension](http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Initializing-Arrays), do `int a[100] = { [0 ... 99] = -1 };` – Johannes Schaub - litb May 23 '10 at 21:37

16 Answers16

45

I'm surprised at all the answers suggesting vector. They aren't even the same thing!

Use std::fill, from <algorithm>:

int directory[100];
std::fill(directory, directory + 100, -1);

Not concerned with the question directly, but you might want a nice helper function when it comes to arrays:

template <typename T, size_t N>
T* end(T (&pX)[N])
{
    return pX + N;
}

Giving:

int directory[100];
std::fill(directory, end(directory), -1);

So you don't need to list the size twice.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 14
    I'm surprised no one has suggested writing out -1 in the initializer list 100 times. – Brian R. Bondy May 23 '10 at 03:54
  • By the way check here: http://stackoverflow.com/questions/2489970/dyanamic-allocation-on-stack-on-run-time/2489989#2489989 where you say that you can't think of any case that a vector shouldn't be used. On that question the OP was asking about arrays too :) – Brian R. Bondy May 23 '10 at 03:58
  • 9
    Just a minor note that for this, `std::fill_n` is a little simpler: `std::fill_n(directory, 100, -1);` – Jerry Coffin May 23 '10 at 06:08
  • 3
    @Brian R. Bondy: I'm surprised nobody suggested doing `memset(directory, -1, ...)`. On 2's complement architecture this will actually set `int` values to `-1` :) – AnT stands with Russia May 23 '10 at 06:19
  • The difference between this question and the other one is that this question deals with a statically sized array. – Dennis Zickefoose May 23 '10 at 06:45
  • @Dennis: I understand the difference, it was just posted for humor given the strong stance about array vs vector difference. – Brian R. Bondy May 23 '10 at 11:26
  • One could also manually initialize an array of 5 integers, and then copy it 20 times to the 100'er one. Though that would probably be disgusting :) – Johannes Schaub - litb May 23 '10 at 21:28
  • 5
    In C++11, `std::fill(std::begin(directory), std::end(directory), -1);` works. – Hindol Aug 23 '12 at 04:32
  • 2
    as every old C programmer knows, the size of a statically allocated array is `sizeof(A)/sizeof(A[0])` – gerardw Sep 04 '13 at 18:28
  • 2
    Regarding _I'm surprised at all the answers suggesting vector. They aren't even the same thing!_ --> But then, I am surprised that no commenter mentioned yet that initialization and assignment are not the same thing either. – Sebastian Mach Jun 05 '14 at 13:00
  • As @SebastianMach pointed out you are not answering the question! So, -1. – Yola Dec 12 '17 at 13:59
9

I would suggest using std::array. For three reasons:
1. array provides runtime safety against index-out-of-bound in subscripting (i.e. operator[]) operations,
2. array automatically carries the size without requiring to pass it separately
3. And most importantly, array provides the fill() method that is required for this problem

#include <array>
#include <assert.h>

typedef std::array< int, 100 > DirectoryArray;

void test_fill( DirectoryArray const & x, int expected_value ) {
    for( size_t i = 0; i < x.size(); ++i ) {
        assert( x[ i ] == expected_value );
    }
}

int main() {
    DirectoryArray directory;
    directory.fill( -1 );
    test_fill( directory, -1 );
    return 0;
}

Using array requires use of "-std=c++0x" for compiling (applies to the above code).

If that is not available or if that is not an option, then the other options like std::fill() (as suggested by GMan) or hand coding the a fill() method may be opted.

Community
  • 1
  • 1
Arun
  • 19,750
  • 10
  • 51
  • 60
  • And most important for me is that it *is* a native array inside. Allocated all on stack and such, if the array instance is on stack. Of course, if there is no C++0x support, `boost::array` or an own wrapped C array will do it too. – Johannes Schaub - litb May 23 '10 at 21:29
  • @Johannes: Yes, that contains a native array inside, is an important point. I missed to mention that. Thanks! – Arun May 23 '10 at 22:06
  • 1
    #1 is wrong: `operator[]` does not perform bounds-checking, only the `.at()` methods (unless you're using certain stdlib impls with debug options that do it on `operator[]` too, but that is definitely not standard behaviour). #2 isn't specific to `std::array`: arrays can be passed by reference, so a trivial template function can determine the size, and in C++17 we have an overload of `std::size()` for that. And #3 is a non sequitur: we can `std::fill()` a plain array too, using pointers to its first and one-past-last elements, which since C++11 can be got using `std::begin()` and `std::end()`. – underscore_d Mar 19 '17 at 18:40
6

If you had a smaller number of elements you could specify them one after the other. Array initialization works by specifying each element, not by specifying a single value that applies for each element.

int x[3] = {-1, -1, -1 };

You could also use a vector and use the constructor to initialize all of the values. You can later access the raw array buffer by specifying &v.front()

std::vector directory(100, -1);

There is a C way to do it also using memset or various other similar functions. memset works for each char in your specified buffer though so it will work fine for values like 0 but may not work depending on how negative numbers are stored for -1.


You can also use STL to initialize your array by using fill_n. For a general purpose action to each element you could use for_each.

fill_n(directory, 100, -1);

Or if you really want you can go the lame way, you can do a for loop with 100 iterations and doing directory[i] = -1;

Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
5

If you really need arrays, you can use boosts array class. It's assign member does the job:

boost::array<int,N> array; // boost arrays are of fixed size!
array.assign(-1);
jopa
  • 1,109
  • 7
  • 6
3

It does work right. Your expectation of the initialiser is incorrect. If you really wish to take this approach, you'll need 100 comma-separated -1s in the initialiser. But then what happens when you increase the size of the array?

johnsyweb
  • 136,902
  • 23
  • 188
  • 247
1

It is working right. That's how list initializers work.

I believe 6.7.8.10 of the C99 standard covers this:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:

  • if it has pointer type, it is initialized to a null pointer;
  • if it has arithmetic type, it is initialized to (positive or unsigned) zero;
  • if it is an aggregate, every member is initialized (recursively) according to these rules;
  • if it is a union, the first named member is initialized (recursively) according to these rules.

If you need to make all the elements in an array the same non-zero value, you'll have to use a loop or memset.

Also note that, unless you really know what you're doing, vectors are preferred over arrays in C++:

Here's what you need to realize about containers vs. arrays:

  1. Container classes make programmers more productive. So if you insist on using arrays while those around are willing to use container classes, you'll probably be less productive than they are (even if you're smarter and more experienced than they are!).
  2. Container classes let programmers write more robust code. So if you insist on using arrays while those around are willing to use container classes, your code will probably have more bugs than their code (even if you're smarter and more experienced).
  3. And if you're so smart and so experienced that you can use arrays as fast and as safe as they can use container classes, someone else will probably end up maintaining your code and they'll probably introduce bugs. Or worse, you'll be the only one who can maintain your code so management will yank you from development and move you into a full-time maintenance role — just what you always wanted!

There's a lot more to the linked question; give it a read.

Community
  • 1
  • 1
Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
  • 3
    `vector`'s are not preferred over arrays. They are two different things. Whichever is best in my current situation is the preferred one. – GManNickG May 23 '10 at 03:43
1

use vector of int instead a array.

vector<int> directory(100,-1);                       // 100 ints with value 1
Satbir
  • 6,358
  • 6
  • 37
  • 52
1

u simply use for loop as done below:-

for (int i=0; i<100; i++)
{ 
a[i]= -1;
}

as a result as u want u can get A[100]={-1,-1,-1..........(100 times)}

T. K. Sah
  • 11
  • 1
1

I had the same question and I found how to do, the documentation give the following example :

std::array<int, 3> a1{ {1, 2, 3} }; // double-braces required in C++11 (not in C++14)

So I just tried :

std::array<int, 3> a1{ {1} }; // double-braces required in C++11 (not in C++14)

And it works all elements have 1 as value. It does not work with the = operator. It is maybe a C++11 issue.

Xavier Bigand
  • 317
  • 3
  • 10
0

Just use this loop.

for(int i =0 ; i < 100 ; i++) directory[i] =0;
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Majid
  • 1
0

the almighty memset() will do the job for array and std containers in C/C++/C++11/C++14

MORTAL
  • 383
  • 2
  • 10
0

Can't do what you're trying to do with a raw array (unless you explicitly list out all 100 -1s in the initializer list), you can do it with a vector:

vector<int> directory(100, -1);

Additionally, you can create the array and set the values to -1 using one of the other methods mentioned.

Stephen
  • 47,994
  • 7
  • 61
  • 70
  • @Brian R. Bondy: Yes, of course, but that's just pedantry. memset,fill,for-loop are fine solutions, but they're not set at initialization. For a raw-array it's {-1,-1,...x100} or set them afterwards. – Stephen May 23 '10 at 04:23
  • ya, I guess at declaration time you have one. – Brian R. Bondy May 23 '10 at 11:19
0

The reason that int directory[100] = {-1} doesn't work is because of what happens with array initialization.

All array elements that are not initialized explicitly are initialized implicitly the same way as objects that have static storage duration.

ints which are implicitly initialized are:

initialized to unsigned zero

All array elements that are not initialized explicitly are initialized implicitly the same way as objects that have static storage duration.

C++11 introduced begin and end which are specialized for arrays!

This means that given an array (not just a pointer), like your directory you can use fill as has been suggested in several answers:

fill(begin(directory), end(directory), -1)

Let's say that you write code like this, but then decide to reuse the functionality after having forgotten how you implemented it, but you decided to change the size of directory to 60. If you'd written code using begin and end then you're done.
If on the other hand you'd done this: fill(directory, directory + 100, -1) then you'd better remember to change that 100 to a 60 as well or you'll get undefined behavior.

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
0

If you are allowed to use std::array, you can do the following:

#include <iostream>
#include <algorithm>
#include <array>
using namespace std;

template <class Elem, Elem pattern, size_t S, size_t L>
struct S_internal {
    template <Elem... values>
    static array<Elem, S> init_array() {
        return S_internal<Elem, pattern, S, L - 1>::init_array<values..., pattern>();
    }
};

template <class Elem, Elem pattern, size_t S>
struct S_internal<Elem, pattern, S, 0> {
    template <Elem... values>
    static array<Elem, S> init_array() {
        static_assert(S == sizeof...(values), "");
        return array<Elem, S> {{values...}};
    }
};

template <class Elem, Elem pattern, size_t S>
struct init_array
{
    static array<Elem, S> get() {
        return S_internal<Elem, pattern, S, S>::init_array<>();
    }
};

void main()
{
    array<int, 5> ss = init_array<int, 77, 5>::get();
    copy(cbegin(ss), cend(ss), ostream_iterator<int>(cout, " "));
}

The output is:

77 77 77 77 77

Yola
  • 18,496
  • 11
  • 65
  • 106
0

Just use the fill_n() method.

Example

int n;
cin>>n;
int arr[n];
int value = 9;
fill_n(arr, n, value); // 9 9 9 9 9...

Learn More about fill_n()

or

you can use the fill() method.

Example

int n;
cin>>n;
int arr[n];
int value = 9;
fill(arr, arr+n, value); // 9 9 9 9 9...

Learn More about fill() method.

Note: Both these methods are available in algorithm library (#include<algorithm>). Don't forget to include it.

Deepam Gupta
  • 2,374
  • 1
  • 30
  • 33
-1

Starting with C++11 you could also use a range based loop:

int directory[10];
for (auto& value: directory) value = -1;
Rev
  • 5,827
  • 4
  • 27
  • 51