106

With the following declaration

int array[ROW][COLUMN]={0};

I get the array with all zeroes but with the following one

int array[ROW][COLUMN]={1};

I don’t get the array with all one value. The default value is still 0.

Why this behavior and how can I initialize with all 1?

EDIT: I have just understood that using memset with value as 1, will set each byte as 1 and hence the actual value of each array cell wont be 1 but 16843009. How do I set it to 1?

Kraken
  • 23,393
  • 37
  • 102
  • 162
  • 1
    @ckruse: The question is not _How_, it's _Why_. – masoud Mar 20 '13 at 10:29
  • @MM. answer is given in the thread I linked. – ckruse Mar 20 '13 at 10:30
  • The problem was actually `why and how` both. :) – Kraken Mar 20 '13 at 10:32
  • @Kraken The question in your edit should perhaps be posted as a separate question from this one. – Lundin Mar 20 '13 at 10:51
  • @Lundin Yeah, I think I am gonna need to do that. Thanks :) – Kraken Mar 20 '13 at 10:53
  • 1
    @Kraken Actually I found that question [here](http://stackoverflow.com/questions/13477281/initializing-an-array-of-ints). I would recommend to do as suggested in my answer (of course!) and not rely on GCC extensions. – Lundin Mar 20 '13 at 10:53
  • @Lundin Looking into it. :) – Kraken Mar 20 '13 at 10:54
  • @Lundin Apart from the `...` operator, I guess all others are plain old answers? Also, If I have to use this operator on 2D array, how do I do it? – Kraken Mar 20 '13 at 10:58
  • @Kraken I have no idea how to use the `...` thing, it is a non-standard GCC extension and therefore I wouldn't recommend it. I'd do some macro solution as in my answer to that question. (The other answers are all suggestions for runtime, which is a bit crude and perhaps not what you need.) – Lundin Mar 20 '13 at 13:28
  • @ckruse The supposed duplicate does not address the {1} issue. – Lundin Mar 20 '13 at 13:29
  • @Lundin it does: „Elements with missing values will be initialized to 0:” (and the following example) – ckruse Mar 20 '13 at 13:34
  • @ckruse But it doesn't explain why. – Lundin Mar 20 '13 at 13:39
  • @Lundin What exactly is „Elements with missing values will be initialized to 0” if not an explanation…? Whatever, it doesn't really matter, obviously I am alone with my opinion :-) and that's ok for me. – ckruse Mar 20 '13 at 13:41
  • @ckruse It is not an explanation, it is a statement: "This is what happens, I will not tell you why." – Lundin Mar 20 '13 at 13:53

7 Answers7

149

You get this behavior, because int array [ROW][COLUMN] = {1}; does not mean "set all items to one". Let me try to explain how this works step by step.

The explicit, overly clear way of initializing your array would be like this:

#define ROW 2
#define COLUMN 2

int array [ROW][COLUMN] =
{
  {0, 0},
  {0, 0}
};

However, C allows you to leave out some of the items in an array (or struct/union). You could for example write:

int array [ROW][COLUMN] =
{
  {1, 2}
};

This means, initialize the first elements to 1 and 2, and the rest of the elements "as if they had static storage duration". There is a rule in C saying that all objects of static storage duration, that are not explicitly initialized by the programmer, must be set to zero.

So in the above example, the first row gets set to 1,2 and the next to 0,0 since we didn't give them any explicit values.

Next, there is a rule in C allowing lax brace style. The first example could as well be written as

int array [ROW][COLUMN] = {0, 0, 0, 0};

although of course this is poor style, it is harder to read and understand. But this rule is convenient, because it allows us to write

int array [ROW][COLUMN] = {0};

which means: "initialize the very first column in the first row to 0, and all other items as if they had static storage duration, ie set them to zero."

therefore, if you attempt

int array [ROW][COLUMN] = {1};

it means "initialize the very first column in the first row to 1 and set all other items to zero".

As for how to initialize the whole array to a specific value/values, see https://stackoverflow.com/a/13488596/584518.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 3
    Thanks for that, anything I can do to intialise the entire array with 1? considering my rows and columns are of size hundreds? – Kraken Mar 20 '13 at 10:51
  • 1
    @Kraken With macro tricks. [See this](http://stackoverflow.com/questions/13477281/initializing-an-array-of-ints/13488596#13488596). – Lundin Oct 24 '14 at 06:22
  • Is it just me or do you need the second set of parenthesis: `int array [ROW][COLUMN] = {{0}};` – user1794469 May 17 '16 at 15:38
  • @user1794469 No you don't. – Lundin May 17 '16 at 19:31
  • I see, it's a warning on gcc 4.9.2: `warning: missing braces around initializer [-Wmissing-braces]` The second set clears the warning. – user1794469 May 18 '16 at 01:24
  • 1
    @user1794469 Yes, and that is good, because in most cases skipping braces is bad practice. But the compiler doesn't _have_ to give a diagnostic. Regarding good/bad practice for this case, see my answer to [this question](http://stackoverflow.com/questions/30350699/multi-dimensional-array-initialization). – Lundin May 18 '16 at 06:13
  • Informative answer, but doesnt answer 'and how can I initialize with all 1' – Tom McLean Feb 06 '23 at 08:56
  • 1
    @TomMcLean I added the link from the above comments to the answer. – Lundin Feb 06 '23 at 09:59
54

If you want to initialize the array to -1 then you can use the following,

memset(array, -1, sizeof(array[0][0]) * row * count)

But this will work 0 and -1 only

akashchandrakar
  • 2,009
  • 3
  • 23
  • 47
user2021512
  • 602
  • 5
  • 7
13
int array[ROW][COLUMN]={1};

This initialises only the first element to 1. Everything else gets a 0.

In the first instance, you're doing the same - initialising the first element to 0, and the rest defaults to 0.

The reason is straightforward: for an array, the compiler will initialise every value you don't specify with 0.

With a char array you could use memset to set every byte, but this will not generally work with an int array (though it's fine for 0).

A general for loop will do this quickly:

for (int i = 0; i < ROW; i++)
  for (int j = 0; j < COLUMN; j++)
    array[i][j] = 1;

Or possibly quicker (depending on the compiler)

for (int i = 0; i < ROW*COLUMN; i++)
  *((int*)a + i) = 1;
teppic
  • 8,039
  • 2
  • 24
  • 37
  • 1
    @Kraken - It doesn't - `0` initialises only the first value too. It then initialises all the rest with `0` by default. – teppic Mar 20 '13 at 10:27
  • @EricPostpischil so, it sets all the bytes with 1, hence if I consider 32bit integer, then if my `value` field in `memset` is 1 then the actual value in the matrix wont be 1 but `2^0 + 2^8 + 2^16 + 2^24`? – Kraken Mar 20 '13 at 10:38
  • @Kraken: Essentially, yes. `memset` sets each byte in its destination to the value it is given, which will not work to set an `int` to 1. `memset` cannot be used to set values of multiple-byte objects unless you want each byte of the object set to the same value. – Eric Postpischil Mar 20 '13 at 10:41
  • @EricPostpischil So there is no way of doing it apart from manually initialising each? Considering my Rows and Columns are even in the few thousands? – Kraken Mar 20 '13 at 10:44
  • @Kraken I've posted an explanation why {1} does not work. And indeed there is no other way than manual initialization. You don't have to type thousands of numbers though, there are macro tricks, but that is perhaps a topic for another question. – Lundin Mar 20 '13 at 10:50
  • @teppic why would the latter one be faster than two for loops? – Kraken Mar 25 '13 at 19:42
  • @Kraken - it may optimise to faster instructions, but I expect a good compiler would generate the same code for both. – teppic Mar 25 '13 at 19:48
  • I think for large values of ROW & COLUMN, storing its multiplication value before the for loop begins would be even faster. For loop will evaluate the multiplication for every iteration. – Yash Tamakuwala Jul 20 '19 at 10:44
12

To initialize 2d array with zero use the below method: int arr[n][m] = {};

NOTE : The above method will only work to initialize with 0;

Gaurav Suthar
  • 221
  • 3
  • 9
10

Note that GCC has an extension to the designated initializer notation which is very useful for the context. It is also allowed by clang without comment (in part because it tries to be compatible with GCC).

The extension notation allows you to use ... to designate a range of elements to be initialized with the following value. For example:

#include <stdio.h>

enum { ROW = 5, COLUMN = 10 };

int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = 1 } };

int main(void)
{
    for (int i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COLUMN; j++)
            printf("%2d", array[i][j]);
        putchar('\n');
    }
    return 0;
}

The output is, unsurprisingly:

 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1

Note that Fortran 66 (Fortran IV) had repeat counts for initializers for arrays; it's always struck me as odd that C didn't get them when designated initializers were added to the language. And Pascal uses the 0..9 notation to designate the range from 0 to 9 inclusive, but C doesn't use .. as a token, so it is not surprising that was not used.

Note that the spaces around the ... notation are essentially mandatory; if they're attached to numbers, then the number is interpreted as a floating point number. For example, 0...9 would be tokenized as 0., ., .9, and floating point numbers aren't allowed as array subscripts. With the named constants, ...ROW-1 would not cause trouble, but it is better to get into the safe habits.


Addenda:

I note in passing that GCC 7.3.0 rejects:

int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = { 1 } } };

where there's an extra set of braces around the scalar initializer 1 (error: braces around scalar initializer [-Werror]). I'm not sure that's correct given that you can normally specify braces around a scalar in int a = { 1 };, which is explicitly allowed by the standard. I'm not certain it's incorrect, either.

I also wonder if a better notation would be [0]...[9] — that is unambiguous, cannot be confused with any other valid syntax, and avoids confusion with floating point numbers.

int array[ROW][COLUMN] = { [0]...[4] = { [0]...[9] = 1 } };

Maybe the standards committee would consider that?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
7

Use vector array instead:

vector<vector<int>> array(ROW, vector<int>(COLUMN, 1));
Jogendra Kumar
  • 894
  • 11
  • 16
3
char grid[row][col];
memset(grid, ' ', sizeof(grid));

That's for initializing char array elements to space characters.

inhaler
  • 175
  • 1
  • 2
  • 12