235

I have this struct:

struct Snapshot
{
    double x; 
    int y;
};

I want x and y to be 0. Will they be 0 by default or do I have to do:

Snapshot s = {0,0};

What are the other ways to zero out the structure?

ks1322
  • 33,961
  • 14
  • 109
  • 164

9 Answers9

311

They are not null if you don't initialize the struct.

Snapshot s; // receives no initialization
Snapshot s = {}; // value initializes all members

The second will make all members zero, the first leaves them at unspecified values. Note that it is recursive:

struct Parent { Snapshot s; };
Parent p; // receives no initialization
Parent p = {}; // value initializes all members

The second will make p.s.{x,y} zero. You cannot use these aggregate initializer lists if you've got constructors in your struct. If that is the case, you will have to add proper initalization to those constructors

struct Snapshot {
    int x;
    double y;
    Snapshot():x(0),y(0) { }
    // other ctors / functions...
};

Will initialize both x and y to 0. Note that you can use x(), y() to initialize them disregarding of their type: That's then value initialization, and usually yields a proper initial value (0 for int, 0.0 for double, calling the default constructor for user defined types that have user declared constructors, ...). This is important especially if your struct is a template.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 3
    This produces lots of warnings in my compiler. – River-Claire Williamson Mar 22 '13 at 18:26
  • 1
    Roger: Try to use the named struct in the initializer, that's what I do and I don't get any warnings in VC 2012: Snapshot s = Snapshot(); – Kit10 Aug 19 '13 at 14:10
  • 1
    @Johannes Schaub - litb Will `Snapshot s = {};` work for non POD members (for zeroing them)? – ontherocks Oct 15 '13 at 09:58
  • 3
    C++11 now allows you to initialize them in the definition of the struct or class, like so: struct Snapshot { double x{0}; //with braces int y = 0 ; //or just old school style 'by assignement' which is really initialization too }; – ikku100 May 05 '16 at 17:36
  • I noticed that `Snapshot s = {3.0};` seems to initialize s.x to 3.0 and s.y to 0. Is this statement standards conforming or relying on implementation? – stewbasic Jan 03 '18 at 05:55
  • 3
    Is "Snapshot s = {};" part of the standard? – Stefan Jul 17 '18 at 13:42
  • @Stefan See https://en.cppreference.com/w/cpp/language/zero_initialization – Morty Mar 12 '19 at 08:42
  • I compiled the same code as C and as C++, to check the `mystruct_t s = {}` syntax. It compiled w/o a problem in both languages. But does it initialize the object to 0 in C as well? – ysap May 21 '20 at 23:23
  • Answering myself: According to this Wikipedia text: https://en.wikipedia.org/wiki/Struct_(C_programming_language)#Initialization , I guess that this applies to C as well, but only for statically allocated objects. Otherwise (i.e., non-static), if at least one member initialiser is given, then the other members are initialized to 0. – ysap May 21 '20 at 23:51
  • @ysap no, `= { }` is not valid C. If it is supported somewhere as an extension I believe it would work exactly as if `{ 0 }` – Antti Haapala -- Слава Україні Aug 17 '20 at 12:43
42

No, they are not 0 by default. The simplest way to ensure that all values or defaulted to 0 is to define a constructor

Snapshot() : x(0), y(0) {
}

This ensures that all uses of Snapshot will have initialized values.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 28
    The downside is that the struct is no longer a POD type, because it has a constructor. That will break some operations such as writing it to a temporary file. – finnw Jul 01 '09 at 15:12
  • 18
    @finnw: C++11 fixes this, although the struct is not POD, it is "standard layout". – Ben Voigt Aug 04 '12 at 23:08
22

In general, no. However, a struct declared as file-scope or static in a function /will/ be initialized to 0 (just like all other variables of those scopes):

int x; // 0
int y = 42; // 42
struct { int a, b; } foo; // 0, 0

void foo() {
  struct { int a, b; } bar; // undefined
  static struct { int c, d; } quux; // 0, 0
}
bdonlan
  • 224,562
  • 31
  • 268
  • 324
  • 1
    That's really not a safe assumption. you shouldn't rely on the value of anything you did not initialize – Hasturkun Jul 01 '09 at 16:02
  • 30
    Static storage duration objects are always initialized to zero - see http://stackoverflow.com/questions/60653/is-global-memory-initialized-in-c/60707#60707 for a citation from the standard. Whether this is good style is another matter. – bdonlan Jul 01 '09 at 16:13
14

With POD you can also write

Snapshot s = {};

You shouldn't use memset in C++, memset has the drawback that if there is a non-POD in the struct it will destroy it.

or like this:

struct init
{
  template <typename T>
  operator T * ()
  {
    return new T();
  }
};

Snapshot* s = init();
AndersK
  • 35,813
  • 6
  • 60
  • 86
  • @LightnessRacesinOrbit oh wat? – pronebird Sep 02 '15 at 17:26
  • @Andy Most Vexing Parse turns things that look like normal ctors -- `SomeType foo();` is the typical one, though it can happen with others -- into function definitions (in that case, a function `foo` that returns `SomeType`). Sorry for the necro, but if anyone else stumbles across this, figured I'd answer. – Nic Nov 03 '17 at 22:53
8

In C++, use no-argument constructors. In C you can't have constructors, so use either memset or - the interesting solution - designated initializers:

struct Snapshot s = { .x = 0.0, .y = 0.0 };
Adrian Panasiuk
  • 7,249
  • 5
  • 33
  • 54
  • 1
    I believe this is C, not C++. It will fail to compile under some C++ compilers. I experienced the compile failure under Cygwin or MinGW. – jww Aug 12 '15 at 07:50
  • This will work in C or C++20. In older C++ standards it will only work if your compiler is gracious. – EinfachToll Jan 28 '21 at 11:57
3

Since this is a POD (essentially a C struct) there is little harm in initialising it the C way:

Snapshot s;
memset(&s, 0, sizeof (s));

or similarly

Snapshot *sp = new Snapshot;
memset(sp, 0, sizeof (*sp));

I wouldn't go so far as to use calloc() in a C++ program though.

finnw
  • 47,861
  • 24
  • 143
  • 221
  • 3
    Same holds for double; all-bits-zero isn't necessarily 0.0 . However, you can check if you have IEEE754 doubles, in which case it must work. – MSalters Jul 02 '09 at 08:54
2

I believe the correct answer is that their values are undefined. Often, they are initialized to 0 when running debug versions of the code. This is usually not the case when running release versions.

Eric
  • 6,364
  • 1
  • 32
  • 49
1

I know this question is super old, but this question popped up for me on google and I found this other way and figured I'd add it here:

Snapshot s {};

I'm not sure what C/C++ language version you need for this syntax.

Simoyd
  • 506
  • 4
  • 11
  • This is probably the best answer for C++11 and newer. I believe it's a special case of _aggregate initialization_? https://en.cppreference.com/w/cpp/language/aggregate_initialization – davidA Dec 01 '21 at 00:56
1

Move pod members to a base class to shorten your initializer list:

struct foo_pod
{
    int x;
    int y;
    int z;
};

struct foo : foo_pod
{
    std::string name;
    foo(std::string name)
        : foo_pod()
        , name(name)
    {
    }
};

int main()
{
    foo f("bar");
    printf("%d %d %d %s\n", f.x, f.y, f.z, f.name.c_str());
}
Bruno Martinez
  • 2,850
  • 2
  • 39
  • 47