Initialize char pointer array in C [duplicate] - c

This question already has answers here:
What will be the value of un-initialized element in the array?
(1 answer)
Are unmentioned struct fields *always* initialised to zero (i.e. when the struct is on the stack)?
(2 answers)
Closed 5 years ago.
Is it safe to initialize some of the elements in the array like this?
const char *str_array[50] = {
[0] = "str_0",
[10] = "str_10",
[24] = "str_24",
[45] = "str_45",
};
Can I rely on the other elements of the array being properly initialized?

The initialization shown in the question is safe, and the elements not specifically initialized with a designated initializer are (in this context) initialized to NULL. In general, the uninitialized elements are initialized the same as a static variable of the same type would be initialized, which is some variation on the theme of 'zero'.
The relevant section of the C standard (ISO/IEC 9899:2011) is §6.7.9 Initialization, and specifically ¶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;151) all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.
151) Any initializer for the subobject which is overridden and so not used to initialize that subobject might not be evaluated at all.
There was a rejoinder in the comments:
What if I want other elements to set to same default value?
Unfortunately, you have to choose NULL (in this case; zero in the general case) as the default value. You don't have any other alternatives in standard C (unlike sophisticated modern languages such as, oh, I dunno — let's think of Fortran 66). There's no way in standard C to repeat an initializer other than by writing it many times.
GCC has an extension that allows you to do that (which is documented in the GCC manual in a section with the title Designated Initializers that documents both standard behaviour and non-standard behaviour). Using the GNU extension, you could write:
const char *str_array[50] = {
[1 ... 49] = "empty string", // GCC extension
[0] = "str_0",
[10] = "str_10",
[24] = "str_24",
[45] = "str_45",
};
Note that it is OK to specify two initializers for a cell (such as 10, 24, 45 — the other is via the repeated initializer); the last one mentioned wins. Also note the space separating the ... from the 1 (and 45); that is crucial because of the 'maximal munch rule' which means that [1...45] would be tokenized as [, 1., ., .45, ], where the floating point numbers are not what's wanted.

Yes, it's quite safe.
See N1570 section 6.7.9.
Paragraph 19, discussing initializer lists:
... all subobjects that are not initialized explicitly shall be
initialized implicitly the same as objects that have static storage
duration.
Paragraph 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;

Related

What value does the compiler assign to an uninitialised member of a const struct in C?

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.

Can't figure out the reason for the output? [duplicate]

This question already has answers here:
Why is this array having all remaining values initialized to zero?
(4 answers)
Does a string literal count as a partial initializer and zero-initialize?
(3 answers)
Closed 4 years ago.
//Language C
int main()
{
int a[5]={0};
for(int i=0 ; i < 4 ; i++ )
printf("%d",a[i]);
}
}
The output of the following was 1000 in gcc. But I thought it should print 1 and rest garbage values as I have not assigned values to other array locations.
If compiler version is not taken in account, is my thinking right? Or I am missing something.
The C standard (citing the latest C11 draft N1570 here) explains this quite well.
§6.7.9 Initialization, p21:
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.
(emphasis mine)
so, every element except a[0] in your code is initialized implicitly. Now let's look what that means:
§6.7.9 Initialization, p10:
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;
(again, emphasis mine)
so, a[1] to a[4] are initialized to 0 -- type int is an arithmetic type.

Unused indices of a global initialized array? [duplicate]

This question already has answers here:
What happens to fields not named by a designated initializer?
(1 answer)
Why is this array having all remaining values initialized to zero?
(4 answers)
Closed 5 years ago.
I have a struct array. Only a few index locations need to be initialized. Is there a compiler attribute that ensures that the uninitialized combinations are init'd to 0 ?
For example:
If I have a statically init'd struct array as below, how can I ensure that the remaining 3 elements in that array (which are not explicitly pre-init'd) are zero'd out ?
typedef struct foo_s {
int a;
int b;
} foo_t;
foo_t foo_array[4] = {
{ .a = 1, .b = 2 },
};
Thanks,
The behavior you want is already part of standard C. There are no "half-initialized" variables; if you only initialize part of something, then all remaining elements will be zero-initialized.
Besides, you say (in your title) that this array is global. That means it has static storage duration, so it will be zero-initialized even if you don't provide any initializer at all.
Quoting C99 on aggregate initializers:
6.7.8/19:
[...] all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.
6.7.8/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.
6.7.8/10:
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.

structure on the stack - fields initialized? [duplicate]

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.

Can we assign less array contents at array inline declaration?

I got an array A which encapsulates M arrays of type B. Each such B array has 3-components.
However, i need my entries to be padded to 4 components. One way to do this, is to modify my values to have a 4-th zero component as:
uint16_t A[M][4] = {{a0,a1,a2,0}, {a3,a4,a5,0}, ... , {aM-1,aM,aM+1,0}};
However, i realize i can declare A as follows and clang is not complaining:
uint16_t A[M][4] = {{a0,a1,a2}, {a3,a4,a5}, ... , {aM-1,aM,aM+1}};
Is this legal? would A's entries be expanded by the compiler to include a 4-th component? Can you please point in the C-standard (PEP) where can i see this behavior explained.
Yes, this should be valid.
Quoting C11, chapter §6.7.9, Initialization
Each brace-enclosed initializer list has an associated current object. When no
designations are present, subobjects of the current object are initialized in order according
to the type of the current object: array elements in increasing subscript order, [...]
and then, (emphasis mine)
The initialization shall occur in initializer list order, each initializer provided for a
particular subobject overriding any previously listed initializer for the same subobject;151)
all subobjects that are not initialized explicitly shall be initialized implicitly the same as
objects that have static storage duration.
According to the C Standard (6.7.9 Initialization)
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;151) all
subobjects that are not initialized explicitly shall be initialized
implicitly the same as objects that have static storage duration.
and
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 arithmetic type, it is initialized to (positive or
unsigned) zero;
And from the C++ Standard (8.5.1 Aggregates)
7 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 its brace-or-equal-initializer or, if there
is no brace-or-equalinitializer, from an empty initializer list
(8.5.4)
And (8.5 Initializers)
3 List-initialization of an object or reference of type T is defined
as follows:
— Otherwise, if the initializer list has no elements, the object is
value-initialized.
and further
8 To value-initialize an object of type T means:
— otherwise, the object is zero-initialized.

Resources