Related
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
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
I have an array I am trying to declare with all it's cells equal to 0. Everytime I try to access any of the cells, except the first, they always return with -858993460, which is definitely not 0.
Here is the declaration of the array:
int values[8] = { };
Here is the array cell being printed, which prints out -858993460.
cout << value.values[1];
This line works fine, though:
cout << value.values[0];
The exact Declaration of the value object (Value is a class):
Value value;
The Declaration of the Value class:
#pragma once
class Value{
public:
int values[8] = { };
Value();
~Value();
};
Only the first cell prints 0, So how can I declare an array with all cells being 0?
For any additional information, here is enough code to reproduce the problem (combine this with the declaration of Value:
#include <iostream>
#include "Value.h"
using namespace std;
int main(){
char null;
Value value;
cout << value.values[1];
cin >> null; //this just holds up the program so I have time to read what it printed
return 0;
}
int values[(2 ^ 3)] = { };
std::cout << values[0];
produces 0 as you would expect. value.values is some other value that you didn't show.
2 ^ 3 equals 1, you probably meant a version of pow. This explains why you get
too many initializer variables
when you use int values[(2 ^ 3)] = { 0,0,0,0,0,0,0,0 };, because values only has 1 element.
int values[8] = {}; will properly initialize all 8 values with 0.
You seem to be assuming that ^ is an exponentiation operator. It isn't; C++ has no exponentiation operator. ^ is bitwise xor, so 2^3 == 1. If you try to access elements with indices greater than 0, you'll get garbage (actually undefined behavior, but a garbage value is a common symptom).
You could use 1 << 3, which yields 8 -- or you could just use 8.
This should work if you're defining a standalone object:
int values[8] = { };
But if values is actually a member of a struct or class (as implied by your use of value.values[0]), it's a different story. If you want information on that, please update the question to show the declaration of values in its correct context.
I get an error on line 6 (initialize my_foo to foo_init) of the following program and I'm not sure I understand why.
typedef struct foo_t {
int a, b, c;
} foo_t;
const foo_t foo_init = { 1, 2, 3 };
foo_t my_foo = foo_init;
int main()
{
return 0;
}
Keep in mind this is a simplified version of a larger, multi-file project I'm working on. The goal was to have a single constant in the object file, that multiple files could use to initialize a state structure. Since it's an embedded target with limited resources and the struct isn't that small, I don't want multiple copies of the source. I'd prefer not to use:
#define foo_init { 1, 2, 3 }
I'm also trying to write portable code, so I need a solution that's valid C89 or C99.
Does this have to do with the ORGs in an object file? That initialized variables go into one ORG and are initialized by copying the contents of a second ORG?
Maybe I'll just need to change my tactic, and have an initializing function do all of the copies at startup. Unless there are other ideas out there?
In C language, objects with static storage duration have to be initialized with constant expressions, or with aggregate initializers containing constant expressions.
A "large" object is never a constant expression in C, even if the object is declared as const.
Moreover, in C language, the term "constant" refers to literal constants (like 1, 'a', 0xFF and so on), enum members, and results of such operators as sizeof. Const-qualified objects (of any type) are not constants in C language terminology. They cannot be used in initializers of objects with static storage duration, regardless of their type.
For example, this is NOT a constant
const int N = 5; /* `N` is not a constant in C */
The above N would be a constant in C++, but it is not a constant in C. So, if you try doing
static int j = N; /* ERROR */
you will get the same error: an attempt to initialize a static object with a non-constant.
This is the reason why, in C language, we predominantly use #define to declare named constants, and also resort to #define to create named aggregate initializers.
It's a limitation of the language. In section 6.7.8/4:
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.
In section 6.6, the spec defines what must considered a constant expression. No where does it state that a const variable must be considered a constant expression. It is legal for a compiler to extend this (6.6/10 - An implementation may accept other forms of constant expressions) but that would limit portability.
If you can change my_foo so it does not have static storage, you would be okay:
int main()
{
foo_t my_foo = foo_init;
return 0;
}
2021: For who reaches this post because of arm-none-eabi-gcc.exe compile error on STM32 MCUs:
Change your toolchain to gnu-tools-for-stm32.9-2020-q2-update.
From GCC V8.1+, nested constant initializer is supported and the code below will be compiled.
const int a = 1;
const int b = a +1;
typedef struct foo_t {
int a, b, c;
} foo_t;
const foo_t foo_init = { 1, 2, 3 };
foo_t my_foo = foo_init;
int main()
{
return 0;
}
arm-none-eabi-gcc.exe in gnu-tools-for-stm32.7-2018-q2-update is based on gcc v7.3.1 and the code above will not compile! But gnu-tools-for-stm32.9-2020-q2-update uses gcc v9.3.1 and will compile.
For more info see these:
Why "initializer element is not a constant" is... not working anymore?
and
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960#c18
Just for illustration by compare and contrast
The code is from http://www.geeksforgeeks.org/g-fact-80/
/The code fails in gcc and passes in g++/
#include<stdio.h>
int initializer(void)
{
return 50;
}
int main()
{
int j;
for (j=0;j<10;j++)
{
static int i = initializer();
/*The variable i is only initialized to one*/
printf(" value of i = %d ", i);
i++;
}
return 0;
}
This is a bit old, but I ran into a similar issue. You can do this if you use a pointer:
#include <stdio.h>
typedef struct foo_t {
int a; int b; int c;
} foo_t;
static const foo_t s_FooInit = { .a=1, .b=2, .c=3 };
// or a pointer
static const foo_t *const s_pFooInit = (&(const foo_t){ .a=2, .b=4, .c=6 });
int main (int argc, char **argv) {
const foo_t *const f1 = &s_FooInit;
const foo_t *const f2 = s_pFooInit;
printf("Foo1 = %d, %d, %d\n", f1->a, f1->b, f1->c);
printf("Foo2 = %d, %d, %d\n", f2->a, f2->b, f2->c);
return 0;
}
There are basically two sorts of initialization: at compile time, and at run time.
The initialization for static-storage variable belongs to the compile-time initialization. Note that the static-storage variable includes:
global variable without the static keyword
global variable with the static keyword
local variable with the static keyword
But what is the principle behind this rule?
In my mind it's simple to explain.
Before the completion of compilation, the values of these variables would be stored into the executable file. And at that time no code can run!
gcc 7.4.0 can not compile codes as below:
#include <stdio.h>
const char * const str1 = "str1";
const char * str2 = str1;
int main() {
printf("%s - %s\n", str1, str2);
return 0;
}
constchar.c:3:21: error: initializer element is not constant
const char * str2 = str1;
In fact, a "const char *" string is not a compile-time constant, so it can't be an initializer. But a "const char * const" string is a compile-time constant, it should be able to be an initializer. I think this is a small drawback of CLang.
A function name is of course a compile-time constant.So this code works:
void func(void)
{
printf("func\n");
}
typedef void (*func_type)(void);
func_type f = func;
int main() {
f();
return 0;
}
I had this error in code that looked like this:
int A = 1;
int B = A;
The fix is to change it to this
int A = 1;
#define B A
The compiler assigns a location in memory to a variable. The second is trying a assign a second variable to the same location as the first - which makes no sense. Using the macro preprocessor solves the problem.
I was wondering in C++ if I have an enum can I access the value at the second index? For example I have
enum Test{hi, bye};
if I want 'hi', can I do something like Test[0], thanks.
Yes and no. If your Enum does not have explicit values then it is possible. Without an explicit values, enum values are given numeric values 0-N in order of declaration. For example ...
enum Test {
hi, // 0
bye // 1
}
This means that indexes just translates into a literal value.
Test EnumOfIndex(int i) { return static_cast<Test>(i); }
This of course does 0 validation at runtime and as soon as you add an explicit value it will break down. But it will work in the default scenario.
Unless specified otherwise, enums start numbering at 0, and increment by 1 each entry.
enum Test
{
hi, //0
bye, //1
count //2
}
You can cast an int to the type of the enum to get the value you want, such as:
(Test)0;
//or
Test(0);
Which lets you do things like:
for(int i = 0; i < count; i++)
{
DoSomething((Test)i);
}
Enumerations map names to values. In your case, (int)hi would have a value of 0, and (int)bye a value of 1. You can use a cast to get the value of hi:
int myInteger = 0;
Test myValue = (Test)myInteger;
Note, though, that myValue could be an invalid enum value if myInteger is out of range.
No, but you could cast from int
Test test = (Test)0;
Depends what you mean by "I want 'hi'".
If you mean you want the value, then you can get it by casting an int, as others have said.
Casting a numeric literal to enum type is usually pointless - if you know which value you're expecting, you can use the name. That way, the enum can change without breaking your code. I guess it's possible that something really weird is going on, where someone has created an enum, and documented what "3" means but not which enum value it is. But then you'd want to fix the API.
Casting an integer value known at runtime to enum might be helpful if you have serialized data. As long as you know it's in range of the enum, the result is defined.
If you mean you want the string "hi", then you can't have it. Unlike Java, in C++ the names of the values in enumerated types exist only at compile time, not at runtime, and only map in one direction.
Your best option might be something like this:
enum Test{hi = 0, bye};
Then you can simply refer to 'hi' with the number 0, and 'bye' with 1.
Although this really defeats the whole purpose of using an enumeration in the first place.
If you are excepting the value to returned as {Hi or bye} ,then you cannot get the value like that .
i would not suggest this to be done inorder to get the actual value but it can be used as hack
string return_value(int index)
{
string temp = "";
switch (index)
{
case 1: temp = "hi"
break;
case 2: temp = "bye";
break;
defualt :
break;
}
return temp;
}
typecasting to enum would again return the index but you can assign to some other enum variable
#include <iostream>
#define GENERATE_ENUM(ENUM) ENUM,
#define GENERATE_STRING(STRING) #STRING,
#define FOREACH_TEST(ID) ID(hi) ID(bye) ID(good)
enum TEST { FOREACH_TEST(GENERATE_ENUM) };
static const char * Test[] = { FOREACH_TEST(GENERATE_STRING) };
int main() {
printf("%s ",Test[0]);
printf("%s\n",Test[bye]);
for (int i=0; i<2; i++) printf("Test[%d] = %s\n", i, Test[i]); }
compile and run with: g++ enum-test.cpp -o enum-test; ./enum-test
output:
hi bye
Test[0] = hi
Test[1] = bye