248

How do I initialise all these variables to zero without declaring each variable on a new line?

int column, row, index = 0;
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Sam
  • 2,497
  • 2
  • 15
  • 3
  • 50
    Careful with those one-line multi-variable declarations. It's easier than you think to declare an int pointer followed by a list of regular integers (`int* a, b, c;` doesn't do what it looks like). – Chris Eberle Jul 27 '11 at 01:16
  • 4
    There are only three variables, dude, write `=0` for each one in their definitions. And, if you really want many variables, then try an array: `int a[10]={0}` will initialize each `a[i]` to 0 for you. – Stan Jul 27 '11 at 01:33
  • 1
    The compiler shouldn't allow that construct if it's going to behave differently than what a reasonable programmer would expect it to do...imho – cph2117 Nov 03 '16 at 22:36
  • 3
    @cph2117 A reasonable programmer would think _'hmm, this syntax could mean a couple of different things depending on how the grammar binds things'_, look up the Standard to find out which is true, and get on with it. – underscore_d May 26 '17 at 22:51
  • 1
    Stop doing this. It just makes code harder to read. The point of writing code in a high level language is to make it simple for a maintainer to read. – Martin York Jun 03 '20 at 15:33

10 Answers10

300
int column = 0, row = 0, index = 0;
Chris Eberle
  • 47,994
  • 12
  • 82
  • 119
Josh
  • 6,155
  • 2
  • 22
  • 26
239

With the following declaration, only the last variable (index) is set to 0:

int column, row, index = 0;

Instead, the following sets all variables to 0:

int column, row, index;
column = index = row = 0;

But personally, I find the following methods much more readable:

int column = 0, row = 0, index = 0;
int column = 0;
int row = 0;
int index = 0;
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
hookenz
  • 36,432
  • 45
  • 177
  • 286
  • 6
    Between the last two I decide based on whether the two values must really be the same type (`bool previousInputValue, presentInputValue;`) or if they just happen to be the same type now but don't really need to be (`uint8_t height, width;` might turn into `uint8_t height; uint16_t width;` in the future and should have been `uint8_t height; uint8_t width;` to begin with). – altendky Jun 17 '15 at 15:08
  • Because writing `uint8_t height; uint16_t width;` instead of `uint8_t height, width;` saves 10 characters in the future. :-) you can of course do it however you like. Just make sure you make it easily read. So the last form is the most explicit. – hookenz Aug 14 '16 at 20:56
  • 1
    The last form is certainly the most explicit at stating the type of each variable and making it clear that each one is initialized. That said, it is not explicit about whether or not column and row are expected to be the same type or not. Perhaps we would both prefer the explicitness of `int presentValue = 0; typeof(presentValue) previousValue = presentValue;`, but I believe that `typeof()` is a non-standard GCC extension. – altendky Aug 14 '16 at 21:20
  • @altendky: C++11 introduced [`decltype`](https://en.cppreference.com/w/cpp/language/decltype) as a portable version of GNU C `typeof`. So `decltype (width) height = 0;` works, but requires more mental effort to read. – Peter Cordes Oct 10 '22 at 15:41
67

As @Josh said, the correct answer is:

int column = 0,
    row = 0,
    index = 0;

You'll need to watch out for the same thing with pointers. This:

int* a, b, c;

Is equivalent to:

int *a;
int b;
int c;
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
  • 49
    I hate that pointer thing, it makes no sense. The asterisk is part of the type, so it should apply to all of them. Imagine if `unsigned long x, y;` declared `x` as `unsigned long` but `y` as just `unsigned`, aka `unsigned int`! That's exactly the same! – Cam Jackson Jan 22 '13 at 05:41
  • 10
    It makes sense. "int *a, b, c;" – Jeroen Jul 26 '13 at 15:10
  • 10
    @JeroenBollen Well yeah, it makes sense if you write your pointer asterisks next to the variable name instead of the type, but that in itself doesn't make any sense. Like I said above, the asterisk is part of the type, not part of the name, so it should by grouped with the type! – Cam Jackson Oct 28 '13 at 13:32
  • 1
    @camjackson Not really, you declare b, c and the value a points to as integers. – Jeroen Nov 01 '13 at 11:25
  • 1
    @JeroenBollen OK, I guess I see that logic, but it still seems totally counter-intuitive to me. Oh well, it's hardly going to change for me! – Cam Jackson Nov 01 '13 at 11:54
  • 18
    As a side not, actually it makes sense the the * isn't necessarily part of the type, as the ``int *a`` means that ``*a`` represents an ``int`` value. – mdenton8 Jan 21 '14 at 07:34
  • 2
    The point has already been made but just to add to it void is essentially the lack of a type but you can still make pointers to it. Thus why `void* a` will compile and `void *a, b, c` won't. This rationalization works for me. – Josh C Oct 21 '15 at 17:26
  • 2
    I think it should be noted that same hold for references (&). Also, if you want them all to be pointers then you could write `int *a, *b;`. I believe it is still part of C++ only because of backwards compatibility. – sluki Dec 09 '15 at 08:21
  • 1
    int* a,b,c; Gets different results than. typedef int* INT_PTR; INT_PTR a,b,c; I would consider "*" part of the type. – KANJICODER Dec 07 '19 at 15:54
  • What if you want b and c to b ints? If the asterisk is part of the type, how do you write that without adding more lines? This way, you can do either one or both in a single line. =D (I'm being silly, but so is the question, so.) – Shavais Aug 03 '20 at 21:52
  • @Shavais You mean `int *a, b, c`? You can do that, but it's better style to declare the variable on the same line that it is first assigned to, e.g. `int b = 1 + 1;`. Failing that, you can also just express each declaration explicitly on its own line. – Mateen Ulhaq Aug 03 '20 at 23:29
  • @Mateen Yes, that's what I meant. And I agree, but, matters of style aside, if int *a, b, c produced 3 pointers, that would be a substantial functional change to the language. A whole lot of existing code would break and there would be a lot of confused and unhappy developers. – Shavais Aug 04 '20 at 17:51
  • 1
    The actual problem is, that parenthesis are not allowed in declarations. If one could write `(int*) a, b, c;`, then it would be possible to declare three pointers without repeating the `*`. Of course, this problem is inherited into C++ from the olden days of C, when (source code) bytes were expensive and programmers wrote things like `char c, arr[255], *s;` – Kai Petzke Sep 02 '20 at 09:44
  • 1
    @CamJackson The way it makes sense is that `int *a, b, *c;` is best thought of as saying `*a`, `b`, and `*c` are each expressions that point at type `int`. That's the mindset/design/model/idea behind C doing it that way, and from that vision it makes a lot of sense. – mtraceur Oct 21 '21 at 08:35
28
int column(0), row(0), index(0);

Note that this form will work with custom types too, especially when their constructors take more than one argument.

Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125
  • 5
    and nowadays with uniform initialisation (pending C++17 fixing this for `auto`...): int column **{** 0 **}** , row **{** 0 **}** , index **{** 0 **}** ; – underscore_d Jun 11 '16 at 18:49
28

If you declare one variable/object per line not only does it solve this problem, but it makes the code clearer and prevents silly mistakes when declaring pointers.

To directly answer your question though, you have to initialize each variable to 0 explicitly. int a = 0, b = 0, c = 0;.

Mark B
  • 95,107
  • 10
  • 109
  • 188
20

As of C++17, you can use Structured Bindings:

#include <iostream>
#include <tuple>

int main () 
{
    auto [hello, world] = std::make_tuple("Hello ", "world!");
    std::cout << hello << world << std::endl;
    return 0;
}

Demo

Olivia Stork
  • 4,660
  • 5
  • 27
  • 40
ivaigult
  • 6,198
  • 5
  • 38
  • 66
  • Is there any way to initialize several variables in a class like that? Without using class constructor and initialization list. I tried to do it, but it seems of a class method it is not possible to use Structural Bindings. – Puya Aug 08 '23 at 11:38
  • 1
    @Puya Not in a class, no. For a class every var should be explicitly declared. – ivaigult Aug 09 '23 at 10:49
11

I wouldn't recommend this, but if you're really into it being one line and only writing 0 once, you can also do this:

int row, column, index = row = column = 0;
Levi Uzodike
  • 391
  • 3
  • 7
5

Possible approaches:

  • Initialize all local variables with zero.
  • Have an array, memset or {0} the array.
  • Make it global or static.
  • Put them in struct, and memset or have a constructor that would initialize them to zero.
Ajay
  • 18,086
  • 12
  • 59
  • 105
4

As others have mentioned, from C++17 onwards you can make use of structured bindings for multiple variable assignments.

Combining this with std::array and template argument deduction we can write a function that assigns a value to an arbitrary number of variables without repeating the type or value.

#include <iostream>
#include <array>

template <int N, typename T> auto assign(T value)
{
    std::array<T, N> out;
    out.fill(value);
    return out;
}

int main()
{
    auto [a, b, c] = assign<3>(1);

    for (const auto& v : {a, b, c})
    {
        std::cout << v << std::endl;
    }

    return 0;
}

Demo

j b
  • 5,147
  • 5
  • 41
  • 60
-18

When you declare a variable without initializing it, a random number from memory is selected and the variable is initialized to that value.

  • 10
    not really. The compiler decides 'this variable will be at address xxx', whatever happened to be at address xxx will be the initial value unless its set to something explicitly (by initialize or assignment) – pm100 Apr 02 '14 at 17:08
  • 5
    @pm100 although _better_, and true for any trivial implementation that doesn't go out of its way to harass users... that's still oversimplifying ;-) as using an uninitialised variable is UB, so _in theory_ anything can happen, including any code using that variable simply being stripped out of the program - which is especially likely when optimisation is in play. – underscore_d Jun 11 '16 at 18:52
  • 1
    the value of that variable would be whatever was at the address it got, i.e. junk. – Pedro V. G. Dec 11 '18 at 05:58
  • 1
    @PedroVernetti It doesn't matter what happened to be at said address before the new variable was declared and happened to get the same address. If the user declares the new variable without initialising it with a value, and then reads the variable before having assigned it a value, the program has undefined behaviour. That's infinitely worse than "random" and "junk" and just needs to be avoided. – underscore_d Jun 16 '19 at 17:03
  • [What happens to uninitialized variables in C/C++?](https://stackoverflow.com/q/70558153) - it's UB in C++ to read an uninitialized variable, except in very limited cases: if it had type `unsigned char` and you're using it to assign or initialize another `unsigned char` (https://en.cppreference.com/w/cpp/language/default_initialization). Then it's just indeterminate, see [Where do the values of uninitialized variables come from, in practice on real CPUs?](https://stackoverflow.com/q/71268001) – Peter Cordes Oct 10 '22 at 16:02