How to initialize a struct to 0 in C++ - c++

Here is a related C answer that doesn't work (as a zero initializer for a struct) in C++: Initializing a struct to 0. One of the solutions presented is this:
myStruct _m1 = {0};
This works fine in C, but it doesn't work in C++. :( :
error: cannot initialize a member subobject of type 'myScope::MyStruct' with an rvalue of type 'int'`.
How do you zero-initialize a struct in C++?
Related:
Initializing
a struct to 0 in C: Initializing a struct to 0
Update: (an adjacent, but NOT duplicate question which also turns out to be very useful) Initialization with empty curly braces
See also:
[adjacently-related, but is for C-style arrays, not structs] How to initialize all members of an array to the same value?
To the people voting to close this question:
My question is not a duplicate of this other question (Initialization with empty curly braces), as this other question isn't asking about the various ways to initialize a struct in C++ and why the C way doesn't work, rather, they are asking why does the C++ keyword explicit break one of their initialization techniques. Two distinct questions. Not duplicate.
Follow-up question I asked:
Why doesn't initializing a C++ struct to = {0} set all of its members to 0?

Before we start:
Let me point out that a lot of the confusion around this syntax comes because in C and C++ you can use the = {0} syntax to initialize all members of a C-style array to zero! See here: https://en.cppreference.com/w/c/language/array_initialization. This works:
// z has type int[3] and holds all zeroes, as: `{0, 0, 0}`
int z[3] = {0};
But, that syntax does not work the same for structs, which are entirely different animals than C-style arrays.
See also my follow-up question I asked after writing this answer below: Why doesn't initializing a C++ struct to = {0} set all of its members to 0?
Back to the answer:
I figured it out: to get it to compile, just delete the zero:
# does NOT work
myStruct _m1 = {0};
# works!
myStruct _m1 = {};
It now compiles. However, I ran a bunch of tests to check some things in my struct_initialization.cpp file in my eRCaGuy_hello_world repo, and that does NOT initialize all elements of the struct to zero! Rather, it initializes the struct to its default values. To run my tests and see for yourself, clone my repo above and run eRCaGuy_hello_world/cpp/run_struct_initialization.sh.
Assuming you have this struct:
typedef struct
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
} data_t;
Note: the typedef above is a carry-over from when I was testing this stuff in C instead of C++ (although the default struct values are not allowed in C, of course). For C++, this is preferred instead:
struct data_t
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
};
So please ignore it wherever I unnecessarily use typedef to define the structs below.
Anyway, if I declare one of the above data_t structs, and then do this:
data_t d2 = {};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
d2.num1, d2.num2, d2.num3, d2.num4);
...the output will be:
d2.num1 = 100
d2.num2 = -100
d2.num3 = 0
d2.num4 = 150
And I'm not even sure if d2.num3 is zero because it was initialized to zero or because it was left uninitialized, and that memory location happened to contain zero.
As explained here: https://en.cppreference.com/w/cpp/language/zero_initialization, you can also do this:
myStruct _m1{};
In the example above, this code:
data_t d2{};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
d2.num1, d2.num2, d2.num3, d2.num4);
...would produce output identical to what I showed above.
Even in cases where setting the struct to = {0} DOES work, such as this:
// Does NOT do what I expected! Only sets the FIRST value in the struct to zero!
// The rest seem to use default values.
data_t d3 = {0};
printf("d3.num1 = %i\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
d3.num1, d3.num2, d3.num3, d3.num4);
...the output is still not what I expected, as it only sets the first value to zero! (I don't understand why):
d3.num1 = 0
d3.num2 = -100
d3.num3 = 0
d3.num4 = 150
On C-style arrays, however (NOT structs), these semantics work fine. Refer to this answer here (How to initialize all members of an array to the same value?). The following lines, therefore, both set all elements of the C-style array to zero when using C++:
uint8_t buffer[100] = {0}; // sets all elements to 0 in C OR C++
uint8_t buffer[100] = {}; // sets all elements to 0 in C++ only (won't compile in C)
So, after much experimentation, it looks like the following several ways are the ONLY ways to zero-initialize a struct, PERIOD. If you know differently, please comment and/or leave your own answer here.
The only ways possible to zero-initialize a struct in C++ are:
Be explicit:
// C-style typedef'ed struct
typedef struct
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
} data_t;
// EXPLICITLY set every value to what you want!
data_t d1 = {0, 0, 0, 0};
// OR (using gcc or C++20 only)
data_t d2 = {.num1 = 0, .num2 = 0, .num3 = 0, .num4 = 0};
Use memset() to force all bytes to zero:
data_t d3;
memset(&d3, 0, sizeof(d3));
Set all default values to zero in the first place:
// C-style typedef'ed struct
typedef struct
{
int num1 = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
} data_t;
// Set all values to their defaults, which are zero in
// this case
data_t d4 = {};
// OR
data_t d5{}; // same thing as above in C++
// Set the FIRST value only to zero, and all the rest
// to their defaults, which are also zero in this case
data_t d6 = {0};
Write a constructor for the C++ struct
// 1. Using an initializer list
struct data
{
int num1;
int num2;
int num3;
int num4;
data() :
num1(0),
num2(0),
num3(0),
num4(0) {}
};
data d7; // all values are zero
// OR: 2. manually setting the values inside the constructor
struct data
{
int num1;
int num2;
int num3;
int num4;
data()
{
num1 = 0;
num2 = 0;
num3 = 0;
num4 = 0;
}
};
data d8; // all values are zero
Use a struct with no default values, and make your object you create from it static
typedef struct
{
int num1;
int num2;
int num3;
int num4;
} data_t;
// `static` forces a default initialization of zero for each
// value when no other default values are set
static data_t d9;
So, if you have a struct with non-zero default values, and you want to zero all values, you must do it EXPLICITLY! Here are some more ways:
// 1. Have a `constexpr` copy of the struct that you use to
// reset other struct objects. Ex:
struct data
{
int num1 = 1;
int num2 = 7;
int num3 = -10;
int num4 = 55;
};
constexpr data DATA_ALL_ZEROS = {0, 0, 0, 0};
// Now initialize d13 to all zeros using the above `constexpr` struct
// object
data d13 = DATA_ALL_ZEROS;
// OR 2. Use a `zero()` member function to zero the values:
struct data
{
int num1 = 1;
int num2 = 7;
int num3 = -10;
int num4 = 55;
zero()
{
num1 = 0;
num2 = 0;
num3 = 0;
num4 = 0;
}
};
data d14;
d14.zero();
The big take-away here is that NONE of these: data_t d{}, data_t d = {}, and data_t d = {0}, actually set all members of a struct to zero!
data_t d{} sets all values to their defaults defined in the struct.
data_t d = {} also sets all values to their defaults.
And data_t d = {0} sets only the FIRST value to zero, and all other values to their defaults.
SO, BE EXPLICIT!
Note that the above key take-aways I wrote seem to contradict this documentation on cppreference.com, so it has led me to ask this follow-up question listed just below, which has proven VERY helpful to my understanding!
Going further
MOST USEFUL: Follow-up question of mine: Why doesn't initializing a C++ struct to = {0} set all of its members to 0?
References:
VERY USEFUL:
https://en.cppreference.com/w/cpp/language/zero_initialization
https://en.cppreference.com/w/cpp/language/aggregate_initialization
https://en.cppreference.com/w/cpp/language/value_initialization
VERY USEFUL: Initializing all members of an array (not struct) to the same value:
How to initialize all members of an array to the same value?
[gcc only] How to initialize all members of an array to the same value?
https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/cpp/struct_initialization.cpp
Clone this repo and run the code yourself with cpp/run_struct_initialization.sh
Related:
Initializing default values in a struct
*****[my own answer, which demonstrate this sort of struct modification/aggregate member reassignment within any function: leds[0] = {10, 20, 30, 40, 50};] Arduino Stack Exchange: Initializing Array of structs

Generically it's not possible. A class may not provide a way to access all members and in those cases the best you can do is value initialize it which will give you a default version of that class.

Objects in C++ are given the ability to control the values of any subobjects within them. As such, C++ has no mechanism that will force zero-initialization onto any object in general.
Objects with no user-provided constructors or default member initializers can undergo zero-initialization in two cases: if the variable is declared static, or if the object is being value-initialized. There are multiple syntaxes that will provoke value initialization of an object, including T(), T{}, and T t = {};, where applicable.
But other than that, if the creator of the type of an object does not want it to be zero-initialized, then you cannot impose that upon the object. You can ask for value-initialization or default-initialization, but whether either of these will invoke zero-initialization depends on the type.

In C++ for types with no constrictor (id est trivially constructible), {} always initializes all bytes to zero, identically the same as { 0 } in C.
PlainOldData pod{};
For types with a constructor, hence not trivially constructable, it makes little sense to initialize all bytes to zero as those objects are meant to control their own state. What you usually want is default initialization, which can usually be done with {}.:
Object obj{};
// or
Object obj;
You can go around this limitation and use memset to clear the memory, but be aware that it will cause a lot of problems with overwriting vtable pointers, et cetera.
memset(&obj, 0, sizeof obj); // dangerous for non-trivial objects

Related

Is a C-struct zero-initialized empty braces in C++? [duplicate]

Here is a related C answer that doesn't work (as a zero initializer for a struct) in C++: Initializing a struct to 0. One of the solutions presented is this:
myStruct _m1 = {0};
This works fine in C, but it doesn't work in C++. :( :
error: cannot initialize a member subobject of type 'myScope::MyStruct' with an rvalue of type 'int'`.
How do you zero-initialize a struct in C++?
Related:
Initializing
a struct to 0 in C: Initializing a struct to 0
Update: (an adjacent, but NOT duplicate question which also turns out to be very useful) Initialization with empty curly braces
See also:
[adjacently-related, but is for C-style arrays, not structs] How to initialize all members of an array to the same value?
To the people voting to close this question:
My question is not a duplicate of this other question (Initialization with empty curly braces), as this other question isn't asking about the various ways to initialize a struct in C++ and why the C way doesn't work, rather, they are asking why does the C++ keyword explicit break one of their initialization techniques. Two distinct questions. Not duplicate.
Follow-up question I asked:
Why doesn't initializing a C++ struct to = {0} set all of its members to 0?
Before we start:
Let me point out that a lot of the confusion around this syntax comes because in C and C++ you can use the = {0} syntax to initialize all members of a C-style array to zero! See here: https://en.cppreference.com/w/c/language/array_initialization. This works:
// z has type int[3] and holds all zeroes, as: `{0, 0, 0}`
int z[3] = {0};
But, that syntax does not work the same for structs, which are entirely different animals than C-style arrays.
See also my follow-up question I asked after writing this answer below: Why doesn't initializing a C++ struct to = {0} set all of its members to 0?
Back to the answer:
I figured it out: to get it to compile, just delete the zero:
# does NOT work
myStruct _m1 = {0};
# works!
myStruct _m1 = {};
It now compiles. However, I ran a bunch of tests to check some things in my struct_initialization.cpp file in my eRCaGuy_hello_world repo, and that does NOT initialize all elements of the struct to zero! Rather, it initializes the struct to its default values. To run my tests and see for yourself, clone my repo above and run eRCaGuy_hello_world/cpp/run_struct_initialization.sh.
Assuming you have this struct:
typedef struct
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
} data_t;
Note: the typedef above is a carry-over from when I was testing this stuff in C instead of C++ (although the default struct values are not allowed in C, of course). For C++, this is preferred instead:
struct data_t
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
};
So please ignore it wherever I unnecessarily use typedef to define the structs below.
Anyway, if I declare one of the above data_t structs, and then do this:
data_t d2 = {};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
d2.num1, d2.num2, d2.num3, d2.num4);
...the output will be:
d2.num1 = 100
d2.num2 = -100
d2.num3 = 0
d2.num4 = 150
And I'm not even sure if d2.num3 is zero because it was initialized to zero or because it was left uninitialized, and that memory location happened to contain zero.
As explained here: https://en.cppreference.com/w/cpp/language/zero_initialization, you can also do this:
myStruct _m1{};
In the example above, this code:
data_t d2{};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
d2.num1, d2.num2, d2.num3, d2.num4);
...would produce output identical to what I showed above.
Even in cases where setting the struct to = {0} DOES work, such as this:
// Does NOT do what I expected! Only sets the FIRST value in the struct to zero!
// The rest seem to use default values.
data_t d3 = {0};
printf("d3.num1 = %i\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
d3.num1, d3.num2, d3.num3, d3.num4);
...the output is still not what I expected, as it only sets the first value to zero! (I don't understand why):
d3.num1 = 0
d3.num2 = -100
d3.num3 = 0
d3.num4 = 150
On C-style arrays, however (NOT structs), these semantics work fine. Refer to this answer here (How to initialize all members of an array to the same value?). The following lines, therefore, both set all elements of the C-style array to zero when using C++:
uint8_t buffer[100] = {0}; // sets all elements to 0 in C OR C++
uint8_t buffer[100] = {}; // sets all elements to 0 in C++ only (won't compile in C)
So, after much experimentation, it looks like the following several ways are the ONLY ways to zero-initialize a struct, PERIOD. If you know differently, please comment and/or leave your own answer here.
The only ways possible to zero-initialize a struct in C++ are:
Be explicit:
// C-style typedef'ed struct
typedef struct
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
} data_t;
// EXPLICITLY set every value to what you want!
data_t d1 = {0, 0, 0, 0};
// OR (using gcc or C++20 only)
data_t d2 = {.num1 = 0, .num2 = 0, .num3 = 0, .num4 = 0};
Use memset() to force all bytes to zero:
data_t d3;
memset(&d3, 0, sizeof(d3));
Set all default values to zero in the first place:
// C-style typedef'ed struct
typedef struct
{
int num1 = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
} data_t;
// Set all values to their defaults, which are zero in
// this case
data_t d4 = {};
// OR
data_t d5{}; // same thing as above in C++
// Set the FIRST value only to zero, and all the rest
// to their defaults, which are also zero in this case
data_t d6 = {0};
Write a constructor for the C++ struct
// 1. Using an initializer list
struct data
{
int num1;
int num2;
int num3;
int num4;
data() :
num1(0),
num2(0),
num3(0),
num4(0) {}
};
data d7; // all values are zero
// OR: 2. manually setting the values inside the constructor
struct data
{
int num1;
int num2;
int num3;
int num4;
data()
{
num1 = 0;
num2 = 0;
num3 = 0;
num4 = 0;
}
};
data d8; // all values are zero
Use a struct with no default values, and make your object you create from it static
typedef struct
{
int num1;
int num2;
int num3;
int num4;
} data_t;
// `static` forces a default initialization of zero for each
// value when no other default values are set
static data_t d9;
So, if you have a struct with non-zero default values, and you want to zero all values, you must do it EXPLICITLY! Here are some more ways:
// 1. Have a `constexpr` copy of the struct that you use to
// reset other struct objects. Ex:
struct data
{
int num1 = 1;
int num2 = 7;
int num3 = -10;
int num4 = 55;
};
constexpr data DATA_ALL_ZEROS = {0, 0, 0, 0};
// Now initialize d13 to all zeros using the above `constexpr` struct
// object
data d13 = DATA_ALL_ZEROS;
// OR 2. Use a `zero()` member function to zero the values:
struct data
{
int num1 = 1;
int num2 = 7;
int num3 = -10;
int num4 = 55;
zero()
{
num1 = 0;
num2 = 0;
num3 = 0;
num4 = 0;
}
};
data d14;
d14.zero();
The big take-away here is that NONE of these: data_t d{}, data_t d = {}, and data_t d = {0}, actually set all members of a struct to zero!
data_t d{} sets all values to their defaults defined in the struct.
data_t d = {} also sets all values to their defaults.
And data_t d = {0} sets only the FIRST value to zero, and all other values to their defaults.
SO, BE EXPLICIT!
Note that the above key take-aways I wrote seem to contradict this documentation on cppreference.com, so it has led me to ask this follow-up question listed just below, which has proven VERY helpful to my understanding!
Going further
MOST USEFUL: Follow-up question of mine: Why doesn't initializing a C++ struct to = {0} set all of its members to 0?
References:
VERY USEFUL:
https://en.cppreference.com/w/cpp/language/zero_initialization
https://en.cppreference.com/w/cpp/language/aggregate_initialization
https://en.cppreference.com/w/cpp/language/value_initialization
VERY USEFUL: Initializing all members of an array (not struct) to the same value:
How to initialize all members of an array to the same value?
[gcc only] How to initialize all members of an array to the same value?
https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/cpp/struct_initialization.cpp
Clone this repo and run the code yourself with cpp/run_struct_initialization.sh
Related:
Initializing default values in a struct
*****[my own answer, which demonstrate this sort of struct modification/aggregate member reassignment within any function: leds[0] = {10, 20, 30, 40, 50};] Arduino Stack Exchange: Initializing Array of structs
Generically it's not possible. A class may not provide a way to access all members and in those cases the best you can do is value initialize it which will give you a default version of that class.
Objects in C++ are given the ability to control the values of any subobjects within them. As such, C++ has no mechanism that will force zero-initialization onto any object in general.
Objects with no user-provided constructors or default member initializers can undergo zero-initialization in two cases: if the variable is declared static, or if the object is being value-initialized. There are multiple syntaxes that will provoke value initialization of an object, including T(), T{}, and T t = {};, where applicable.
But other than that, if the creator of the type of an object does not want it to be zero-initialized, then you cannot impose that upon the object. You can ask for value-initialization or default-initialization, but whether either of these will invoke zero-initialization depends on the type.
In C++ for types with no constrictor (id est trivially constructible), {} always initializes all bytes to zero, identically the same as { 0 } in C.
PlainOldData pod{};
For types with a constructor, hence not trivially constructable, it makes little sense to initialize all bytes to zero as those objects are meant to control their own state. What you usually want is default initialization, which can usually be done with {}.:
Object obj{};
// or
Object obj;
You can go around this limitation and use memset to clear the memory, but be aware that it will cause a lot of problems with overwriting vtable pointers, et cetera.
memset(&obj, 0, sizeof obj); // dangerous for non-trivial objects

set member of array to zero

Morning,
I hope somebody is here
suppose I have the following structure or even better an array of structures
struct foo {
int a;
char b[10];
char c;
};
struct foo* bar;
bar = (struct foo*) malloc(sizeof(struct foo)*10);
memset(bar, -1, sizeof(struct foo)*10);
instead of
for (counter = 0; counter < 10; ++counter)
memset(bar[counter],0,sizeof(char)*10);
how to a set b member to 0 in all array of char / b member in all array?
basically my question is a bit similar to this one
I'd like to suggest that rather than using a C-style array of int b[10]; that you use std::array<char,10> b; instead.
Then you can fill it with zeros this way: b.fill(0);.
If you need to pass the address of the storage to a C-style function you can do that using b.data().
And of course, you can still access its content using b[i], but if you want more safety, use b.at(i).
http://en.cppreference.com/w/cpp/container/array
You can set the b member of each array element to zero by setting the b member of each array element to zero. You were almost there, but:
You only wanted to zero the b member.
The thing you're zeroing isn't 8 bytes long.
for (counter = 0; counter < 10; ++counter)
memset(bar[counter].b, 0, sizeof bar[counter].b);

C++ understanding Unions and Structs

I've come to work on an ongoing project where some unions are defined as follows:
/* header.h */
typedef union my_union_t {
float data[4];
struct {
float varA;
float varB;
float varC;
float varD;
};
} my_union;
If I understand well, unions are for saving space, so sizeof(my_union_t) = MAX of the variables in it. What are the advantages of using the statement above instead of this one:
typedef struct my_struct {
float varA;
float varB;
float varC;
float varD;
};
Won't be the space allocated for both of them the same?
And how can I initialize varA,varB... from my_union?
Unions are often used when implementing a variant like object (a type field and a union of data types), or in implementing serialisation.
The way you are using a union is a recipe for disaster.
You are assuming the the struct in the union is packing the floats with no gaps between then!
The standard guarantees that float data[4]; is contiguous, but not the structure elements. The only other thing you know is that the address of varA; is the same as the address of data[0].
Never use a union in this way.
As for your question: "And how can I initialize varA,varB... from my_union?". The answer is, access the structure members in the normal long-winded way not via the data[] array.
Union are not mostly for saving space, but to implement sum types (for that, you'll put the union in some struct or class having also a discriminating field which would keep the run-time tag). Also, I suggest you to use a recent standard of C++, at least C++11 since it has better support of unions (e.g. permits more easily union of objects and their construction or initialization).
The advantage of using your union is to be able to index the n-th floating point (with 0 <= n <= 3) as u.data[n]
To assign a union field in some variable declared my_union u; just code e.g. u.varB = 3.14; which in your case has the same effect as u.data[1] = 3.14;
A good example of well deserved union is a mutable object which can hold either an int or a string (you could not use derived classes in that case):
class IntOrString {
bool isint;
union {
int num; // when isint is true
str::string str; // when isint is false
};
public:
IntOrString(int n=0) : isint(true), num(n) {};
IntOrString(std::string s) : isint(false), str(s) {};
IntOrString(const IntOrString& o): isint(o.isint)
{ if (isint) num = o.num; else str = o.str); };
IntOrString(IntOrString&&p) : isint(p.isint)
{ if (isint) num = std::move (p.num);
else str = std::move (p.str); };
~IntOrString() { if (isint) num=0; else str->~std::string(); };
void set (int n)
{ if (!isint) str->~std::string(); isint=true; num=n; };
void set (std::string s) { str = s; isint=false; };
bool is_int() const { return isint; };
int as_int() const { return (isint?num:0; };
const std::string as_string() const { return (isint?"":str;};
};
Notice the explicit calls of destructor of str field. Notice also that you can safely use IntOrString in a standard container (std::vector<IntOrString>)
See also std::optional in future versions of C++ (which conceptually is a tagged union with void)
BTW, in Ocaml, you simply code:
type intorstring = Integer of int | String of string;;
and you'll use pattern matching. If you wanted to make that mutable, you'll need to make a record or a reference of it.
You'll better use union-s in a C++ idiomatic way (see this for general advices).
I think the best way to understand unions is to just to give 2 common practical examples.
The first example is working with images. Imagine you have and RGB image that is arranged in a long buffer.
What most people would do, is represent the buffer as a char* and then loop it by 3's to get the R,G,B.
What you could do instead, is make a little union, and use that to loop over the image buffer:
union RGB
{
char raw[3];
struct
{
char R;
char G;
char B;
} colors;
}
RGB* pixel = buffer[0];
///pixel.colors.R == The red color in the first pixel.
Another very useful use for unions is using registers and bitfields.
Lets say you have a 32 bit value, that represents some HW register, or something.
Sometimes, to save space, you can split the 32 bits into bit fields, but you also want the whole representation of that register as a 32 bit type.
This obviously saves bit shift calculation that a lot of programmers use for no reason at all.
union MySpecialRegister
{
uint32_t register;
struct
{
unsigned int firstField : 5;
unsigned int somethingInTheMiddle : 25;
unsigned int lastField : 6;
} data;
}
// Now you can read the raw register into the register field
// then you can read the fields using the inner data struct
The advantage is that with a union you can access the same memory in two different ways.
In your example the union contains four floats. You can access those floats as varA, varB... which might be more descriptive names or you can access the same variables as an array data[0], data[1]... which might be more useful in loops.
With a union you can also use the same memory for different kinds of data, you might find that useful for things like writing a function to tell you if you are on a big endian or little endian CPU.
No, it is not for saving space. It is for ability to represent some binary data as various data types.
for example
#include <iostream>
#include <stdint.h>
union Foo{
int x;
struct y
{
unsigned char b0, b1, b2, b3;
};
char z[sizeof(int)];
};
int main()
{
Foo bar;
bar.x = 100;
std::cout << std::hex; // to show number in hexadec repr;
for(size_t i = 0; i < sizeof(int); i++)
{
std::cout << "0x" << (int)bar.z[i] << " "; // int is just to show values as numbers, not a characters
}
return 0;
}
output: 0x64 0x0 0x0 0x0 The same values are stored in struct bar.y, but not in array but in sturcture members. Its because my machine have a little endiannes. If it were big, than the output would be reversed: 0x0 0x0 0x0 0x64
You can achieve the same using reinterpret_cast:
#include <iostream>
#include <stdint.h>
int main()
{
int x = 100;
char * xBytes = reinterpret_cast<char*>(&x);
std::cout << std::hex; // to show number in hexadec repr;
for (size_t i = 0; i < sizeof(int); i++)
{
std::cout << "0x" << (int)xBytes[i] << " "; // (int) is just to show values as numbers, not a characters
}
return 0;
}
its usefull, for example, when you need to read some binary file, that was written on a machine with different endianess than yours. You can just access values as bytearray and swap those bytes as you wish.
Also, it is usefull when you have to deal with bit fields, but its a whole different story :)
First of all: Avoid unions where the access goes to the same memory but to different types!
Unions did not save space at all. The only define multiple names on the same memory area! And you can only store one of the elements in one time in a union.
if you have
union X
{
int x;
char y[4];
};
you can store an int OR 4 chars but not both! The general problem is, that nobody knows which data is actually stored in a union. If you store a int and read the chars, the compiler will not check that and also there is no runtime check. A solution is often to provide an additional data element in a struct to a union which contains the actual stored data type as an enum.
struct Y
{
enum { IS_CHAR, IS_INT } tinfo;
union
{
int x;
char y[4];
};
}
But in c++ you always should use classes or structs which can derive from a maybe empty parent class like this:
class Base
{
};
class Int_Type: public Base
{
...
int x;
};
class Char_Type: public Base
{
...
char y[4];
};
So you can device pointers to base which actually can hold a Int or a Char Type for you. With virtual functions you can access the members in a object oriented way of programming.
As mentioned already from Basile's answer, a useful case can be the access via different names to the same type.
union X
{
struct data
{
float a;
float b;
};
float arr[2];
};
which allows different access ways to the same data with the same type. Using different types which are stored in the same memory should be avoided at all!

Correct and simplest syntactical way to initialise an array to 0 [duplicate]

This question already has answers here:
How to initialize all members of an array to the same value?
(26 answers)
Closed 8 years ago.
I am trying to find out the correct way to initialise an array to all zeros (i.e. as if you have done a memset on the array).
I have found the following methods from various areas in stack overflow (and other sources):
char myArray1[10] = {0};
char myArray2[10] = {0,};
char myArray3[10] = {[0 ... 9] = 0};
char myArray4[10] = {0,0,0,0,0,0,0,0,0,0};
I would prefer the simplest syntax variant... I was using {0}, but I have not found any proof this actually is correct.
Missing elements in an array will be initialised to 0. In addition, C++ allows you to leave the uniform initialiser empty. So the following works, is minimal and also the most efficient:
T array[N] = {};
It’s worth noting that this works for any type T which can be either default-constructed or initialised, not just built-in types. For example, the following works, and will print foo five times:
#include <iostream>
struct foo {
foo() { std::cout << "foo()\n"; }
};
int main() {
foo arr[5] = {};
}
A more extensive list of the different possibilities was posted by aib some time ago.
From the C++ specification, "Aggregate initialization" (8.5.1):
If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list.
So each char not in the initializer list would be initialized to char() that is 0.
In C++11 you can type:
char a[10] = {};
char b[10]{};
Some old compilers (or was it in C) may require you add at least one member:
char a[10] = {0};
Naturally, if the array has static lifetime (global or static variable), then it will be zero initialized if there is not initializer:
char global_array[10];
I find it confusing, so I prefer to add the = {} anyway.
About the trailing comma, it is useful if you do something like:
char a[] = {
1,
2,
3,
};
So that you don't make a special case for the last line and you make copy&paste and diffs easier. In your specific case is just useless:
char a[10] = {0,};
That comma does nothing, and it is ugly, so I wouldn't write it.
I prefer this because it is simple yet explicit:
char myArray1[10] = { 0 };

initialize char array - C and C++

I was asked what this syntax means:
char data[32] = {1};
However I can't remember what it does,. but I remember that it's valid.
Can anyone explain its purpose ?
This will create an array of 32 chars. The first element will be 1 and the rest will be set to zero.
If you do not initialize an automatic array (local and not static) at all, the elements of the array may contain garbage values.
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
char data[5];
for (i = 0; i < 5; i++) {
printf("data[%d] = %d\n", i, data[i]);
}
return 0;
}
Output:
data[0] = 72
data[1] = 12
data[2] = -118
data[3] = 51
data[4] = -119
However, if you do initialize it, it will be initialized with the initializers you have specified. If the number of initializers is less than the total number of the elements in the array, the remaining elements will be initialized to 0.
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
char data[5] = {1};
for (i = 0; i < 5; i++) {
printf("data[%d] = %d\n", i, data[i]);
}
return 0;
}
Output:
data[0] = 1
data[1] = 0
data[2] = 0
data[3] = 0
data[4] = 0
It is initialisation. It sets the first element of the array of a value of 1 (^A in the ASCII table I checked) and the remainder to 0 (default).
To state the C99 standard on omitted initializers:
If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, or fewer characters in a string literal used to initialize an array of known
size than there are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration.
and:
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.
And char is an arithmetic type, so the remaining elements of the array will be initialised to zero.
Yes, you recall correctly. Just Google for "C array initialization":
http://www.eskimo.com/~scs/cclass/notes/sx4aa.html
A couple of notes:
Under older, pre-ANSI C compilers, you could not always supply
initializers for "local" arrays inside functions; you could only
initialize "global" arrays, those outside of any function. Those
compilers are now rare, so you shouldn't have to worry about this
distinction any more.
When an array definition includes an initializer, the array
dimension may be omitted, and the compiler will infer the dimension
from the number of initializers
If there are fewer initializers than elements in the array, the
remaining elements are automatically initialized to 0.