what value an array gets when intiallized - c

In C, when I declare an array:
char MyArray[100] = { 0 };
What is the value inserted into the array's elements?
Is it possible to fill it with NULLs?

In this case, all elements will be initialized with null character '\0'.
C11-§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.
and paragraph 10 says that
[...] 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;
Is it possible to fill it with NULLs?
NULL is a macro which is used for null pointers and not for null characters.

In the declaration
char MyArray[100] = { 0 };
all elements are initialized to zero. Filling it with NULL:s makes no real sense, however you can use the character constant '\0' if that is what you mean.

In C the preprocessor macro NULL is defined (by several headers, including <stdio.h> and <stddef.h>) as a null pointer constant, typically 0 or ((void *)0).
So basically you can only initialize values to 0 (or \0 for char) which your code is doing for the entire array, NULL has a different purpose - its not the same as null in other languages like C# or Java.
Even if you wrote:
char MyArray[100] = { 65 };
The remaining elements will be initialized to 0 by the Compiler.
NULL should be used only as a pointer constant

In this case, all the memory attributable to the array is set to \0.
This is true in general with the exception of pointers which are initialised to the null pointer value (which might be 0 but the C standard does not insist on that).
Note that the NULL of C does not denote a null reference value as it does in other languages such as Java.

Compiler set default value for omitted array elements. The compiler that reserves the 100 zero bytes in the data segement of the program.

You initialized all elements of your array with the value 0, this is what = { 0 } stands for in an initialization expression.
Filling with NULL is non-sense as NULL is value defined for pointers and your array is an array of chars not pointer to something.
Maybe what you would like is to set the value to something that would mean not defined yet, but this does not exists in C. Every variable, at the time, it is defined, as a value. NULL doesn't mean no value, but does not point to something; but it is a value!

Related

Where is the null-character in a fixed-length empty string? [duplicate]

This question already has answers here:
C char array initialization: what happens if there are less characters in the string literal than the array size?
(6 answers)
Closed 6 years ago.
So I got curious reading some C code; let's say we have the following code:
char text[10] = "";
Where does the C compiler then put the null character?
I can think of 3 possible cases
In the beginning, and then 9 characters of whatever used to be in memory
In the end, so 9 characters of garbage, and then a trailing '\0'
It fills it completely with 10 '\0'
The question is, depending on either case, whether it's necessary to add the trailing '\0' when doing a strncpy. If it's case 2 and 3, then it's not strictly necessary, but a good idea; and if it's case 1, then it's absolutely necessary.
Which is it?
In your initialization, the text array is filled with null bytes (i.e. option #3).
char text[10] = "";
is equivalent to:
char text[10] = { '\0' };
In that the first element of text is explicitly initialized to zero and rest of them are implicitly zero initialized as required by C11, Initialization 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.
Quoting N1256 (roughly C99), since there are no relevant changes to the language before or after:
6.7.8 Initialization
14 An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
"" is a string literal consisting of one character (its terminating null character), and this paragraph states that that one character is used to initialise the elements of the array, which means the first character is initialised to zero. There's nothing in here that says what happens to the rest of the array, but there is:
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.
This paragraph states that the remaining characters are initialised the same as if they had static storage duration, which means the rest of the array gets initialised to zero as well.
Worth mentioning here as well is the "if there is room" in p14:
In C, char a[5] = "hello"; is perfectly valid too, and for this case too you might want to ask where the compiler puts the null character. The answer here is: it doesn't.
String literal "" has type of character array char[1] in C and const char [1] in C++.
You can imagine it the following way
In C
chat no_name[] = { '\0' };
or
in C++
const chat no_name[] = { '\0' };
When a string literal is used to initialize a character array then all its characters are used as initializers. So for this declaration
char text[10] = "";
you in fact has
char text[10] = { '\0' };
All other characters of the array that do not have corresponding initializers (except the first character that is text[0]) then they are initialized by 0.
From the C Standard (6.7.9 Initialization)
14 An array of character type may be initialized by a character string
literal or UTF−8 string literal, optionally enclosed in braces.
Successive bytes of the string literal (including the terminating null
character if there is room or if the array is of unknown size)
initialize the elements of the array.
and
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
and at last
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;
The similar is written in the C++ Standard.
Take into account that in C you may write for example the following way
char text[5] = "Hello";
^^^
In this case the character array will not have the terminating zero because there is no room for it. :) It is the same as if you defined
char text[5] = { 'H', 'e', 'l', 'l', 'o' };

What happens when the length of a string is greater than the length of it's characters?

char matrix_string[1000] = "the";
In the code above, is the resulting string "the" followed by a bunch of zeros or garbage values? What should I do if I know that this string will be getting bigger as I will be appending values to it?
Any time you initialize an array with fewer items than the array can hold, the remainder of the array is initialized to zero. Using a string literal as an initializer is no different. When you use a string literal to initialize an array, all of the array elements after the string will be initialized to zero.
The following quote is from the C11 specification, §6.7.9 paragraph 21 (emphasis added)
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 this is what §6.7.9 paragraph 10 says about the initialization of objects that have static storage duration
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;
So the line
char matrix_string[1000] = "the";
puts 't','h','e','\0' in the first four elements of the array and sets the other 996 elements to 0.
It depends.
If matrix_string is a global variable, then the remainder of the bytes are initialised to zeros.
If matrix_string is a local variable, then the remainder of the bytes (after the first four bytes including the trailing nul) are uninitialised.
is the resulting string "the" followed by a bunch of zeros or garbage values?
It will be all zeros (or NULL characters) after "the". You can just check by printf matrix_string[5] for example, with different control %c (shows nothing) and %d (show zero).

what are the initial values of pointers in "array of pointers"?

Before putting my question, I want to quote "Expert C Programming" [Page :276, last paragraph]:
"The beauty of Illiffe vector data structre is that it allows arbitrary arrays of pointers to strings to be passed to functions, but only arrays of pointers, and only pointers to strings.
This is because both strings and pointers have the convention of an explicit out-of-bound value(NUL and NULL, respectively) that can be used as an end marker."
So, What I understood from above text is that if there is an array of pointers they have explicit out-of-bound value like NULL.( Correct me , if I'm wrong...)
So, it left me wondering what are the default values of an array of pointers(thinking that an array of pointers would have last pointer as NULL). Tried below code-snippets and result was very different.
int *x[2];
printf("%p %p",x[0],x[1]);
Output is: (nil) 0x400410
int *x[3];
printf("%p %p %p",x[0],x[1],x[2]);
Output is: 0xf0b2ff 0x400680 (nil)
int *x[4];
printf("%p %p %p %p", x[0],x[1],x[2],x[3]);
Output is: (nil) 0x4003db 0x7fffe48e4776 0x4006c5
So, with the above outputs , it is clear that there is an explicit Out-of-Bound (nil) value assigned to one of the pointers(one pointer is NIL), but is it truly the end-marker? No.
Is it one of those "Implementation defined" things of C-language?
I'm using a GCC compiler(4.6.3) on a Ubuntu machine.
Is it one of those "Implementation defined" things of C-language?
No, that's not implementation-defined - it's plain "undefined". The same is true for arrays of all types: the values that you see in them are undefined until explicitly initialized.
What I understood from above text is that if there is an array of pointers they have explicit out-of-bound value like NULL.
The author wanted to say that there is a value (specifically, NULL value) that can be used to mark a "no value" in an array of pointer. The author did not mean to imply that such a no-value marker would be placed into an array of pointers by default.
An array, or any object, with automatic storage duration (i.e., any object defined within a function body without the static keyword) has no default initial value unless you specify one. Its initial value is garbage, and you must not access that value before assigning something to it.
An object with static storage duration (i.e., any object defined outside any function and/or with the static keyword) is initialized to zero, with the meaning of "zero" (0 for integers, 0.0 for floating-point, null for pointers) applied recursively to subobjects.
You can use an initializer to ensure that a pointer object is set to a null pointer, or to whatever value you like:
int *x[2] = { NULL, NULL };
or, more simply:
int *x[2] = { 0 }; /* sets first element to 0, which is converted to a null
pointer; other elements are implicitly set to null
pointers as well */
You are misreading the quotation from "Expert C Programming." The key phrase there is the following:
This is because both strings and pointers have the *convention* of an explicit
out-of-bound value (NUL and NULL, respectively).
It is possible and even conventional to have an array of strings such that the last pointer is set to NULL. This can allow one to iterate over the array quite easily without knowing exactly how many elements there are in the array:
char* dwarves[] = { "Dopey",
"Grumpy",
"Sleepy",
"Happy",
"Sneezy",
"Bashful",
"Doc",
NULL
};
But you have to explicitly set the last pointer to NULL. Such structures are useful because they allow elegant code. So if you want to print or otherwise manipulate the array, you don't need to worry about how many strings are in it, as the NULL pointer will signal the end:
for (char** pWalk = dwarves; *pWalk; pWalk++)
printf ("%s\n", *pWalk);
The beauty of this particular type of ragged-array structure is that strings by definition have a built-in NUL terminator, and the array of pointers is terminated with the NULL, so the endpoints of both dimensions are known. However, the NULL as the last pointer in the array is not something that's built into the language. It has to be explicitly set. Failing to do so would be the equivalent of declaring an array of char but not terminating it with a NUL:
char myString[] = { 'H', 'e', 'l', 'l', 'o' } // No NUL termination
Just as you would have to know how many characters there are in this array if you want to manipulate it in any useful way, without the NULL at the end of the array of pointers, manipulating it would be more difficult.
That's really all that Peter van der Linden is saying in the paragraph you quoted about Illiffe data structures.
There is no requirement in C that any local variable should have any 'default' value. So, when the compiler reserves two (or three) memory locations, the initial value is whatever that these memory locations contained before - there will not be any default initialization.
Unless your array was declared at file scope (outside of any function) or with the static keyword, the array contents will not be initialized; each element will contain some random bit pattern that may or may not correspond to a valid address.
If your array was declared at file scope or with the static keyword, then each element would be implicitly initialized to NULL. Note that attempting to dereference a NULL pointer results in undefined behavior, so you will want to check that your pointer isn't NULL before doing something with it.
A null pointer represents a well-defined "nowhere", guaranteed to compare unequal to any valid memory address. Note that there is a null pointer constant1 and a null pointer value2, and the two are not necessarily the same. In your source code, the macro NULL is set to the null pointer constant. During translation, each occurence of NULL in your source code is replaced with the real null pointer value.
There are invalid pointer values other than NULL; it's just that NULL is well-defined and works the same everywhere.
1. Any 0-valued integral expression, as used in a pointer context. Could be a naked 0, or (void *) 0, or something else that evaluates to 0.
2. Value used by the platform to represent a null pointer, which does not have to be 0.

Char Array Initialization

How does this work::
char Test1[8] = {"abcde"} ;
AFAIK, this should be stored in memory at Test1 as
a b c d e 0 SomeJunkValue SomeJunkValue
instead it get stored as:
a b c d e 0 0 0
Initializing only adds one trailing NULL char after the string literals but how and why all other array members are initialized to NULL ?
Also, any links or any conceptual idea on what is the underlying method or function that does:char TEST1[8] = {"abcde"} ; would be very helpful.
How is:
char Test1[8] = {"abcde"} ;
different from
char Test1[8] = "abcde" ;
?
Unspecified members of a partially initialized aggregate are initialized to the zero of that type.
6.7.9 Initialization
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.
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; [...]
For the array char Test1[8], the initializers {"abcde"} and "abcde" are completely equivalent per 6.7.9:14:
An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces.

Calloc with structure with pointers in C

I know that calloc request memory to be used, writes 0 on all the bits and then returns a pointer to it.
My question is: if I use calloc with a structure that contains pointers, will those pointers have the NULL value or do I have to set them to point to NULL?
struct a{
char * name;
void * p;
}* A;
So basically, will name and p point to NULL after I've used calloc with struct a?
Thanks!
Somehow you've gotten a lot of incorrect answers. C does not require the representation of null pointers to be all-zero-bits. Many people mistakenly think it does, since an integer constant expression with value 0, converted to a pointer, becomes a null pointer.
With that said, on all real-world systems, null pointers are all-zero-bits, and calloc is a perfectly reasonable way to get a null-pointer-initialized pointer array in the real world.
R.'s answer is good, but I'd like to add the standard quotes to support this, and show a way to 0 initialize your struct that does, in fact, yield NULL pointers.
From N1548 (C11 draft)
7.22.3.2 The calloc function allocates space for an array of nmemb objects, each of whose size
is size. The space is initialized to all bits zero.[289]
The footnote then says (emphasis added):
Note that this need not be the same as the representation of floating-point zero or a null pointer constant.
While a null pointer is usually represented as all 0 bits, this representation is not guaranteed. To answer your question directly, no you cannot rely on the calloc()'d struct's pointers to be NULL.
If you want to set all contained pointers of a dynamically allocated struct to NULL you can use the following:
struct a *s = malloc(sizeof *s);
*s = (struct a){0};
C11:
6.7.9.21
If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, [...] the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration
and
6.7.9.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;
C requires you to have at least one element inside the braces, which is why I use {0} instead of {}. The rest of the elements are initialized according to the above rules, which results in null pointers. As far as I can tell, the rules for this are the same in C11 and C99.
The ISO C standard for calloc requires it to initialize everything to 0. That means that if you end up veiwing memory allocated by calloc as pointers, it will indeed initially contain NULL (0) pointers.

Resources