I would like to ask you: Are the elements of static structure initialized to zero? For example:
static struct _radioSettings
{
unsigned char radio_in;
unsigned char radio_out;
}radioSettings;
So this structure is placed in module radio-settings.c
If radioSettings.radio_in and radioSettings.radio_out are not initialized to zero at compilation how can I initialize them inside the module radio-settings.c?
All global variables are initialized to the default values.
Section 6.7.8 Initialization of C99 standard (n1256) says:
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.
So for your structure, each field is initialized to its default value, that is 0.
Static, in C, is related to the visibility of the structure, it does not mean anything else than it is not visible from outside module radio-settings.c.
Structures in C are not initialized to anything. The values for its fields are the memory values the structure landed in. So, you cannot count on anything like that.
If you want to initialize the structure, then it is simple:
memset( &radioSettings, 0, sizeof( _radioSettings ) );
You only have to place that in an init() function for the radioSettings, inside the module radio-settings.c
Hope this helps.
Related
Say I have a struct typedef that is:
typedef struct {
int32_t memberOne;
int32_t memberTwo;
} myStruct_t;
I instantiate a const of that type as follows:
const myStruct_t myConst = {.memberTwo = 32};
What does C say the compiler should set memberOne to be? I've tried it, of course, and I happen to get 0 on the compilers I've tried, what I'm after here is does the C standard require uninitialised members of a const struct to be initialised to something or other by the compiler, i.e. would the code above be considered portable? Clause 6.7.9 of C99 says:
If an object that has static or thread 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, and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
...but what about consts? Are they considered to be of static storage type, just without the static keyword?
does the C standard require uninitialised members of a const struct to be initialised to something
Yes, they are guaranteed to be set to zero/null pointers as long as you initialize at least one member explicitly. const plays no part in it.
You've already found the relevant part about how objects with static storage duration are initialized. Just keep reading the same chapter:
C17 6.7.9 §19
The initialization shall occur in initializer list order, each initializer provided for a
particular subobject overriding any previously listed initializer for the same subobject;
all subobjects that are not initialized explicitly shall be initialized implicitly the same as
objects that have static storage duration.
C17 6.7.9 §21
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.
Do we need to memset global C style strings or is it initiated to '\0' on its own?
for example:
char c_string[10];
OR
struct node
{
int x;
char y[10];
};
Global variables having arithmetic types (including char) are initialized to zero, so you don't use memset() for the first initialization.
Quote from N1570 6.7.9 Initialization 10:
If an object that has static or thread 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,
and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these
rules, and any padding is initialized to zero bits;
File scope variables ("global") have static storage duration. All variables with static storage duration are automatically initialized to zero (or NULL).
However, relying on this initialization is bad practice - it is better to make a habit of writing
char c_string[10] = "";
even if that makes no practical difference. This is self-documenting code meaning that you have actually considered the zero-initialization, rather than char c_string[10]; which could as well mean that you got it right by luck.
This question already has an answer here:
C struct automatic initialization values, array initializations
(1 answer)
Closed 4 years ago.
Consider the following code:
void func()
{
int p;
...
if (p > MAX) {
struct my_struct s;
...
/* here we access the contents 's' as '&s' */
}
}
In this snippet s is on the stack. Is it guaranteed that the compiler initializes all structure fields to zero?
If a variable (struct or otherwise) is declared local to a function or a containing scope (i.e. has automatic storage duration), it is not initialized in any way. You need to explicitly set the fields in the struct.
If you initialize at least one field of a struct but not all, then the remaining fields will be initialized the same as file scope variables (i.e. variables with static storage duration), which means NULL for pointer types and 0 for numeric types.
From section 6.7.9 of the C standard:
10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that
has static or thread 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, and any padding is initialized
to zero bits;
— if it is a union, the first named member is
initialized (recursively) according to these rules, and any padding is
initialized to zero bits;
...
21 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.
No, it's quite the opposite.
Since s is an automatic storage local scoped (i.e., block scoped) variable, unless initialized explicitly, the contents are indeterminate.
Quoting C11, chapter §6.7.9
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. [...].
However, if you want to zero-initialize the variable for an(y) aggregate type, you can simply use an initialization statement like
aggregate-type variable = {0};
which uses the following property from paragraph 21 of the same chapter, (emphasis mine)
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.
No, they won't be initialized at all. The structure values will end up with whatever garbage is on the stack where the structure is placed.
Does C guarantees that an unsigned integer field inside a struct gets initialized to zero? In my system, it seems it does (or I am very "lucky"(actually unlucky)).
In code words, what will happen in the following scenario?
struct node {
unsigned int rec_size;
};
struct node node;
// what is the value of node.rec_size? Undefined or 0?
Relevant answer, but not the same, since in my example, there is only one field and no initialization.
The answer is, it depends on the storage-class:
If it is _Thread_local or static, it is guaranteed to be zeroed.
If it is auto or dynamic storage, no initialization takes place.
6.7.9 Initialization
10 If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. If an object that has static or thread 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,
and any padding is initialized to zero bits;
if it is a union, the first named member is initialized (recursively) according to these
rules, and any padding is initialized to zero bits;
BTW: Zero-initialization in C++ is equivalent to those rules for static/thread-local objects.
No, the value is undetermined.
Value will be 0 only if the variable is static or global.
I have a question about the initialization of static variables in C. I know if we declare a global static variable that by default the value is 0. For example:
static int a; //although we do not initialize it, the value of a is 0
but what about the following data structure:
typedef struct
{
int a;
int b;
int c;
} Hello;
static Hello hello[3];
are all of the members in each struct of hello[0], hello[1], hello[2] initialized as 0?
Yes, all members are initialized for objects with static storage. See 6.7.8/10 in the C99 Standard (PDF document)
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.
To initialize everything in an object, whether it's static or not, to 0, I like to use the universal zero initializer
sometype identifier0 = {0};
someothertype identifier1[SOMESIZE] = {0};
anytype identifier2[SIZE1][SIZE2][SIZE3] = {0};
There is no partial initialization in C. An object either is fully initialized (to 0 of the right kind in the absence of a different value) or not initialized at all.
If you want partial initialization, you can't initialize to begin with.
int a[2]; // uninitialized
int b[2] = {42}; // b[0] == 42; b[1] == 0;
a[0] = -1; // reading a[1] invokes UB
Yes, they are, as long they have static or thread storage duration.
C11 (n1570), § 6.7.9 Initialization #10
If an object that has static or thread storage duration is not initialized
explicitly, then:
[...]
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,
and any padding is initialized to zero bits;
[...]
Yes, file-scope static variables are initialized to zero, including all members of structures, arrays, etc.
See this question for reference (I'll vote to close this as a duplicate, too).
Edit: this question is getting much better answers, so I'm voting to close that question as a duplicate of this, instead.
For reference, here is the C FAQ link from that question's accepted answer, although of course the C99 and C11 standards linked here are canonical.
I would add that static variables (or arrays) are classified into two types.
Initialized are the ones that are given value from code at compile time. These are usually stored in DS though this is compiler specific.
The other type is uninitialized statics which are initialized at run time and are stored into BSS segment though again this is compiler specific.
BSS
For the ones who don't want to read the standard, it's also mentioned in https://en.cppreference.com/w/c/language/initialization :
Implicit initialization
If an initializer is not provided:
objects with automatic storage duration are initialized to indeterminate values (which may be trap representations)
objects with static and thread-local storage duration are zero-initialized