When I declare an int variable, and do not not assign a value to it, and then when I print it, a random number gets printed.
but when I allocate a char variable, and print it with %c format specifier, nothing is printed. So does a char variable in C have a default value like null? Do local variables in C start with a random value? Then why doesn't a char behave in this way?
There is no default value which is assigned to it. Some values are not printable and you can assume that random value is one of them, so that is the reason why you are not able to see the result.
The C99 standard says that:
If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate.
On a side note:
As per C99
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.
Automatic variables that are not initialized have indeterminate value, we can see this by going to the draft C99 standard section 6.7.8 Initialization:
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate.
using an indeterminate value is undefined behavior. The definition for indeterminate values is as follows:
either an unspecified value or a trap representation
It just may be the case that the values you are ending up with for char are not printable.
There is not default value assigned. Never trust in a default value you didn't assign.
Related
I am getting the output "ma" on executing the following code. If my understanding is correct, local variable is not initialized to 0. So in such a case, how come %s is finding 0 in a1[2] itself? Is that we cannot predict the output in such cases and I am somehow getting this result and this may not be the case always?
int main(void)
{
char a1[10];
a1[0]='m';
a1[1]='a';
a1[3]='j';
printf("%s",a1);
return(0);
}
Yes, unless a1 is static note, being an automatic local variable, this is all by-luck. Your code (snippet) produces undefined behavior by missing the terminating null.
It just happens to have the immediate next byte as null, so it is printing properly. It is nowhere guaranteed that it will work very next time.
FWIW, %s format specifier expects a string and the definition of a string in C is a null-terminated char array. To copy the exact wordings,
If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type. [..] If the
precision is not specified or is greater than the size of the array, the array shall contain a null character.
Note: Related to the initialization of static variables, quoting C11 standard, chapter §6.7.9, Initialization, (emphasis mine)
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;
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.
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.
e.g.
union
{
int n;
void *p;
} u;
Is the initial value of u.n or that of u.p equal to 0?
It should be noted that a NULL pointer is not necessarily stored in all-zero bits. Therefore, even if u.n and u.p have the same size,
u.n == 0
doesn't guarantee
u.p == 0
and vice versa.
(Sorry for my poor English)
if Object with 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 u.n will be initilaized to zero and u.p is undetermined.
EDIT: Response to comment
above info copied from ISO/IEC 9899:201x 6.7.9.10
Since u is static then the first member will be initialized to zero, from the C99 draft standard section 6.7.8 Initialization paragraph 10:
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.
since n is a arithmetic type it will be initialized to zero. The value of p is unspecified but in practice type punning is usually supported by the compiler for example the gcc manual points here for Type-punning and we can see under -fstrict-aliasing section is says:
The practice of reading from a different union member than the one most recently written to (called “type-punning”) is common. Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type.
It is also worth noting that you may be able to initialize any member of a union like so:
union { int n; void *p; } u = { .p = NULL } ;
^^^^^^^^^^^^^
I am not sure if all compilers support this though.
I think by 'global variable' you mean that it's at file scope. If so, and if it's declared 'static', it will be initialized to all zero bits, eg because it gets allocated in .BSS.
What those zero bits in the union's storage mean in terms of the value of whichever of its members you access depends on their types. In your case, all zero bits in an int means it has the value zero, and all zero bits in a pointer makes it NULL, ie #Dukeling's bang on here.
I am not sure that all zero bits in a float would yield a float with value zero.
It depends upon how you instantiate the variable itself. Usually static defined variables are initialized to zero. If you malloc the union to a pointer, you may get uninitialized memory. However, if you use calloc to allocate memory for the union, calloc will initialized the allocated memory to zero per the man page.
It may also depend on any libraries that you may be using. Google's perftools library may or may not zero out the memory when you make the call to calloc that it overwrites.
What should the code print? 0 or any garbage value or will it depend on the compiler?
#include <stdio.h>
int a;
int main()
{
printf("%d\n",a);
return 0;
}
the answer is 0. Global variables are initialized to zero.
I would say your code might output anything or simply anything can happen because your code invokes Undefined Behaviour as per C99.
You don't have a prototype for printf in scope.
J.2 Undefined behavior
— For call to a function without a function prototype in scope where the function is defined with a function prototype, either the prototype ends with an ellipsis or the types of the arguments after promotion are not compatible with the types of the parameters (6.5.2.2).
If the question is about initialization of global variables then a would be initialized to 0 because it has static storage duration.
I found on C99 standard, Section 6.7.8.10, Initialization:
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.
Section 6.2.4.3 defines:
An object whose identifier is declared with external or internal linkage, or with the
storage-class specifier static has static storage duration. Its lifetime is the entire
execution of the program and its stored value is initialized only once, prior to program
startup.
In other words, globals are initialized as 0. Automatic variables (i.e. non-static locals) are not automatically initialized.
without automatic variable [generally what we use in function in most cases] all other variable's value is assigned to 0
Global variables are initialized as 0. Automatic variables (i.e. non-static locals) are not automatically initialized.