266

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

int column, row, index = 0;
5
  • 55
    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). Commented Jul 27, 2011 at 1:16
  • 5
    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
    Commented Jul 27, 2011 at 1: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
    Commented Nov 3, 2016 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. Commented May 26, 2017 at 22:51
  • 2
    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. Commented Jun 3, 2020 at 15:33

11 Answers 11

317
int column = 0, row = 0, index = 0;
3
  • Hi, I wonder if this expression support all type like std::vector<float> etc or only the primary data type
    – littlefish
    Commented May 18, 2021 at 10:40
  • 1
    Does this work in C also? Commented Jan 19, 2023 at 11:51
  • @littlefish Of course it supports all types. See syntax (1) and (6) here: en.cppreference.com/w/cpp/language/copy_initialization As the variable is defined in the line, it calls a constructor and not the assignment operator of the type.
    – Sebastian
    Commented Feb 5 at 20:14
252

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;
4
  • 8
    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
    Commented Jun 17, 2015 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
    Commented Aug 14, 2016 at 20:56
  • 2
    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
    Commented Aug 14, 2016 at 21:20
  • 1
    @altendky: C++11 introduced decltype as a portable version of GNU C typeof. So decltype (width) height = 0; works, but requires more mental effort to read. Commented Oct 10, 2022 at 15:41
74

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;
14
  • 53
    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! </rant> Commented Jan 22, 2013 at 5:41
  • 11
    It makes sense. "int *a, b, c;"
    – Jeroen
    Commented Jul 26, 2013 at 15:10
  • 11
    @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! Commented Oct 28, 2013 at 13:32
  • 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
    Commented Jan 21, 2014 at 7:34
  • 4
    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
    Commented Oct 21, 2015 at 17:26
30

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;.

29
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.

1
  • 6
    and nowadays with uniform initialisation (pending C++17 fixing this for auto...): int column { 0 } , row { 0 } , index { 0 } ; Commented Jun 11, 2016 at 18:49
21

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

2
  • 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
    Commented Aug 8, 2023 at 11:38
  • 1
    @Puya Not in a class, no. For a class every var should be explicitly declared.
    – ivaigult
    Commented Aug 9, 2023 at 10:49
13

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;
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.
3
  • #define COLUMN 0 #define ROW 1 #define INDEX 2 #define AR_SIZE 3 int Data[AR_SIZE]; // Just an idea.
    – Ajay
    Commented Jul 28, 2011 at 1:44
  • Sorry, I meant, why did you include the line "Have an array, memset or {0} the array." in your answer? Commented Jul 28, 2011 at 2:16
  • memset(Data, 0, sizeof(Data)); // If this can be packed logically.
    – Ajay
    Commented Jul 28, 2011 at 2:19
5

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

1

Pointers and references have similar syntax.

Some examples for newbies like me:

// correct.
int a = 1, b = 2, c = 3;
int *pa = &a, *pb = &b, *pc = &c;
int &ra = a, &rb = b, &rc = c;
a=4; b=5; c=6;
std::cout << ra << "," << rb << "," << rc << '\n'; // 4,5,6 (what we want)
std::cout << *pa << "," << *pb << "," << *pc << '\n'; // 4,5,6 (what we want)


// incorrect.
int a = 1, b = 2, c = 3;
// int* pa = &a, pb = &b, pc = &c; // error: invalid conversion from 'int*' to 'int'
int& ra = a, rb = b, rc = c;
a=4; b=5; c=6;
std::cout << ra << "," << rb << "," << rc << '\n'; // 4,2,3 (not 4,5,6)
-20

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

7
  • 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
    Commented Apr 2, 2014 at 17:08
  • 6
    @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. Commented Jun 11, 2016 at 18:52
  • 1
    the value of that variable would be whatever was at the address it got, i.e. junk. Commented Dec 11, 2018 at 5:58
  • 2
    @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. Commented Jun 16, 2019 at 17:03
  • 1
    What happens to uninitialized variables in C/C++? - 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 (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? Commented Oct 10, 2022 at 16:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.