Where do the results of an uninitialized array in C come from? Are they randomly assigned values or it's just previous values that are stored in the memory?
#include <stdio.h>
int main (void)
{
int values[10];
int index;
values[0] = 197;
values[2] = -100;
values[5] = 350;
values[3] = values[0] + values[5];
values[9] = values[5] / 10;
--values[2];
for ( index = 0; index < 10; index++ )
printf ("values[%i] = %i\n", index, values[index]);
return 0;
}
and the output:
$ ./a.exe
values[0] = 197
values[1] = 0
values[2] = -101
values[3] = 547
values[4] = 8
values[5] = 350
values[6] = 51
values[7] = 0
values[8] = 44045216
values[9] = 35
Chapter and verse:
6.2.4 Storage durations of objects
...
5 An object whose identifier is declared with no linkage and without the storage-class
specifier static has automatic storage duration, as do some compound literals. The
result of attempting to indirectly access an object with automatic storage duration from a
thread other than the one with which the object is associated is implementation-defined.
6 For such an object that does not have a variable length array type, its lifetime extends
from entry into the block with which it is associated until execution of that block ends in
any way. (Entering an enclosed block or calling a function suspends, but does not end,
execution of the current block.) If the block is entered recursively, a new instance of the
object is created each time. The initial value of the object is indeterminate. If an
initialization is specified for the object, it is performed each time the declaration or
compound literal is reached in the execution of the block; otherwise, the value becomes
indeterminate each time the declaration is reached.
Emphasis added.
Basically, objects with auto storage duration are not implicitly initialized to any particular value - they have the value of whatever was last written to that particular memory location1. You cannot rely on that value being 0 (or anything else).
That last sentence in the quote above applies to situations like this:
for (;;)
{
int x;
do_something_with( x );
}
Each iteration of the loop effectively destroys and re-creates x, and you cannot rely on value written to x in any iteration of the loop to be carried over to the next iteration. In practice on x86-like systems it most likely will be carried over, but don't assume that's the case everywhere.
Note that an implementation may decide to initialize auto variable with some known value when building in debug mode or something.
The mechanics of which are wide and varied and not worth going into here.
What do you think "uninitialized" means?
It means the value has not been set.
Because it has not been set, it could have any value stored there.
Maybe 0, maybe 547...
Any value is valid, and there are no guarantees what you will find.
Uninitialized values are just memory addresses that have not yet been written to by your application. It would be like having a notepad that is used by everyone around you. When your program runs, it's given a small section of that notepad that may or may not have been used by someone else before. If it was (most likely), then it will still have something written on it, but probably will not make any sense to you. If you want to know what's there, you must write something. In general, we will write 0's to it which is like erasing everything to start with empty paper.
Well this is C programming 101.
C is a procedure-oriented language and does not implement some features present in Object Oriented languages (such a Java) such as "automatic" and guaranteed initialization of variables.
If you declare an auto variable (on stack not dynamically allocated) in C and do not provide an initial value, then this variable will have what we call a "garbage value". This is the general behavior but specific implementations can vary.
Let me give an example:
int a; //a variable with no initial value
printf("%d", a);
We can't predict what this will print. May be 0 or may be anything else. The program can crash too. Essentially, this is undefined behavior.
If the same was done in Java, then that would surely print 0 (because Java initializes all integers to 0 by default).
Now coming to your array question: It does not matter whether this is a single integer or an array of integers. Any memory location to which you don't assign a value explicitly will have a "garbage value". It can be 0 or something else. This behavior is completely machine dependent and unpredictable.
Bottom line is: ensure that variables are initialized before use.
Related
Why my code is showing this kind of behavior?
#include <stdio.h>
void s1()
{
int a;
a++;
printf("%d ",a);
}
void s2()
{
int aa;
aa++;
printf("%d ",aa);
}
int main()
{
int i = 0;
for(i = 0; i < 10; i++)
{
s1();
}
for(i = 0; i < 10; i++)
{
s2();
}
return 0;
}
Output: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Why 'a' in second function is storing value from first function?
When you do not initialize an object with automatic storage duration (such as variables defined inside functions), the C standard does not specify what its value is, or even that it has a fixed value, or even (depending on certain factors) that the behavior of the program is defined.
In your case, it is likely the memory that was assigned for a initially contained zero, and the compiler generated code that used this uninitialized memory. After s1 completed, the program used the same memory for aa, the same way that, if you go the dentist and hang your coat on a hook and later take it and leave, a patient who comes after you may hang their own coat on the same hook. Then, in s2, aa contained the value left over from s1.
In “real world” programs, you are unlikely to see this exact behavior, for several reasons. For one, things will have happened in the program before s1 is called, so the memory used for a is not likely to contain zero. For another, the program will be compiled with optimization, and the compiler will likely use a register for a or aa rather than memory on the stack. Further, with optimization turned on, the compiler may recognize that the behavior is not defined or not fully specified and optimize it to even stranger code. And, finally, professionals compile with many warning options enabled and set to be errors rather than mere warnings, so the compiler reports errors like this before the program is deployed.
Congratulations, you've stumbled into Undefined Behavior. Not the first one either.
When you declare a variable with no initialization. The C standard defines it as Indeterminate Values.
3.19.2
1 indeterminate value
either an unspecified value or a trap representation
Any time you try to use an indeterminate value, you invoke undefined behavior. Anything can happen! It may take another variable's value, it may short out the sun, anything!
The Undefined Behavior section of the C standard lists this as one possible UB-
The value of an object with automatic storage duration is used while it is indeterminate.
When you do a++ (or aa++), you're incrementing the current value of a, the value being indeterminate. And thus, the language has no guarantees on the behavior. Just because it shows one behavior in one machine, doesn't mean it'll show the same behavior in all machines.
I wrote the below code to find the sum of all digits in C, and when I compiled and ran it, it was successful.
But, only later I realized that i had not entered any value for the variable 'n' in the for loop's condition.
I'm confused on how this program works, even when there is no value assigned to the condition variable.
I would like to be clarified of the same.
#include<stdio.h>
void main()
{
int no,a,b,n,sum=0;
printf("Enter the number to be added");
scanf("%d",&no);
for(int i=0;i<n;i++)
{
a=no%10;
b=no/10;
sum=a+sum;
no=b;
}
printf("The sum is %d",sum);
}
I'm confused on how this program works
Well, "works" is a very poor observation / decision here. This is undefined behavior.
You're attempting to use the value of an automatic local variable n while it is indeterminate. This invokes the UB.
To quote the C11 standard, chapter §6.7.9
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. [...]
So, in your case, n meets the criteria described above, and hence the content is indeterminate.
Now, after that, in case you try to use a variable while it holds indeterminate value and either
does not have the address taken
can have trap representation
the usage will lead to undefined behavior. That is exactly the case here.
That said, for a hosted environment, the conforming signature of main() is int main(void), at least.
An uninitialized variable MUST contain some value - every address in a computer must have some combination of 1's and 0's even if those values are useless. Therefore it is given a random one when first created if you do not initialize it to something yourself. Often it isn't even "given" data so much as it "takes on" whatever value was at the address it was given to live at when created, but different environments will handle this "non-initialization" differently. You are essentially getting lucky right now under your current conditions.
For that reason this kind of code is considered to have undefined behavior because you are not guaranteed to get lucky like that in every situation. Be safe and always initialize values for variables because this can be a hard thing to catch later when code that used to work suddenly doesn't.
n is not initialized, so is worth anything present at the allocated memory location when run. So if you're lucky, after a few iterations no is 0 and the result is correct but it's just luck.
In your case, you don't need n, just stop when division yields 0 (that's probably why you forgot to initialize n)
while(no!=0)
{
a=no%10;
b=no/10;
sum+=a;
no=b;
}
Why does this code below compiles and executes but doesn't print anything in output,
int i = 0;
printf(i = 0);
but this gives a runtime error,
int i = 0;
printf(i = 1);
int i = 0;
printf(i = 0);
The first argument to printf must be a char* value pointing to a format string. You gave it an int. That's the problem. The difference in behavior between printf(i = 0) and printf(i = 1) is largely irrelevant; both are equally wrong. (It's possible that the first passes a null pointer, and that printf detects and handles null pointers somehow, but that's a distraction from the real problem.)
If you wanted to print the value of i = 0, this is the correct way to do it:
printf("%d\n", i = 0);
You have a side effect in the argument (i = 0 is an assignment, not a comparison), which is legal but poor style.
If you have the required #include <stdio.h>, then your compiler must at least warn you about the type mismatch.
If you don't have #include <stdio.h>, then your compiler will almost certainly warn about calling printf without a declaration. (A C89/C90 compiler isn't strictly required to warn about this, but any decent compiler should, and a C99 or later compiler must.)
Your compiler probably gave you one or more warnings when you compiled your code. You failed to include those warnings in your question. You also failed to show us a complete self-contained program, so we can only guess whether you have the required #include <stdio.h> or not. And if your compiler didn't warn you about this error, you need to find out how to ask it for better diagnostics (we can't help with that without knowing which compiler you're using).
Expressions i = 0 and i = 1 in printf function will be evaluated to 0 and 1 (and i will be initialized to 0 and 1) respectively. So above printf statements after their expression evaluation will be equivalent to
printf(0); // To be clear, the `0` here is not a integer constant expression.
and
printf(1);
respectively.
0 and 1 both will be treated as address in printf statements and it will try to fetch string from these addresses. But, both 0 and 1 are unallocated memory addresses and accessing them will result in undefined behavior.
printf requires a const char * for input, whereas you're giving it an int
printf awaits a format string as its first argument. As strings (char*) are nothing else than pointers, you provide an address as the first parameter.
After an address and an integer are implicitly converted into each other,
printf(i = 0)
is (from the perspective of printf) the same as:
printf( 0 )
which is the same as
printf( NULL ) // no string given at all
If you provide 0 as parameter, printf will gracefully handle that case and don't do anything at all, because 0 is a reserved address meaning nothing at all.
But printf( 1 ) is different: printf now searches for a string at address 1, which is not a valid address for your program and so your program throws a segmentation fault.
[update]
The main reason why this works is a combination of several facts you need to know about how char arrays, pointers, assignments and printf itself work:
Pointers are implicitly convertible to int and vice versa, so the int value 17 for example gets converted to the memory address 0x00000011 (17) without any further notice. This is due to the fact that C is very close to the hardware and allows you to calculate with memory addresses. In fact, internally an int (or more specific: one special type of an integer) and a pointer are the same, just with a different syntax. This leads to a lot of problems when porting code from 32bit to 64bit-architecture, but this is another topic.
Assignments are different from comparations: i = 0 and i == 0 are totally different in meaning. i == 0 returns true when i contains the value 0 while i = 0 returns... 0. Why is that? You can concatenate for example the following variable assignments:
a = b = 3;
At first, b = 3 is executed, returning 3 again, which is then assigned to a. This comes in handy for cases like testing if there is more items in an array:
while( (data = get_Item()) )
This now leads to the next point:
NULL is the same as 0 (which also is the same as false). For the fact that integers and pointers can be converted into each other (or better: are physically the same thing, see my remarks above), there is a reserved value called NULL which means: pointing nowhere. This value is defined to be the virtual address 0x00000000 (32bit). So providing a 0 to a function that expects a pointer, you provide an empty pointer, if you like.
char* is a pointer. Same as char[] (there is a slight logical difference in the behaviour and in the allocation, but internally they are basically the same). printf expects a char*, but you provide an int. This is not a problem, as described above, int will get interpreted as an address. Nearly every (well written) function taking pointers as parameters will do a sanity check on these parameters. printf is no exclusion: If it detects an empty pointer, it will handle that case and return silently. However, when providing something different, there is no way to know if it is not really a valid address, so printf needs to do its job, getting interrupted by the kernel when trying to address the memory at 0x00000001 with a segmentation fault.
This was the long explanation.
And by the way: This only works for 32-bit pointers (so compiled as 32-bit binary). The same would be true for long int and pointers on 64-bit machines. However, this is a matter of the compiler, how it converts the expression you provide (normally, an int value of 0 is implicitly cast to a long int value of 0 and then used as a pointer address when assigned, but vice versa won't work without an explicit cast).
Why does this code below compiles and executes but doesn't print anything in output?
printf(i = 0);
The question embodies a false premise. On any modern C compiler, this clearly-erroneous code generates at least one error.
Good evening guys,
This is a little program shown below. I'm seeking for garbage value of b in every execution, but get the same answer.
The code is simple as follows:
#include<stdio.h>
#include<conio.h>
int main(void)
{
int a = 300, b,c;
if (a>=400)
b=300;
c=200;
printf("\n%d\n%d",b,c);
getch();
}
The o/p in Codeblocks is as follow
2
200
but if I remove the line
b=300;
keeping the semicolon, then it gives garbage values.
Why is this contradiction happening?
Reading uninitialized variable follow below rules,
Static variable are by default initialized to zero means local static or file scope variable (global one).
Non-static variables which local to function are indeterminate. Reading them prior to assigning a value results in undefined behavior. compiler is free to do any thing. It can be zero, it can be the value that was in there, it can crash the program. you have absolutely no guarantees.
It will simply give you the last value that was stored in that position on the stack (or in that register if the variable happens to be stored in a register).
Also undefined might be different between different compilers.
Here 2 is garbage only, you should print the value of b before 'if-statement' and see if it matches with the last print statement. If it matches then both are garbage values and no change occurred to them because of the 'if-statement'.
The question about how compiler generates a garbage value is unpredictable/random.
Explanation:
Step 1: int a = 300, b, c; here variable a is initialized to '300', variable b and c are declared, but not initialized.
Step 2: if(a >= 400) means if(300 >= 400). Hence this condition will be failed.
Step 3: c = 200; here variable c is initialized to '200'.
Step 4: printf("%d, %d, %d\n", a, b, c); It prints "300, garbage value, 200". because variable b is not initialized.
I have defined a variable with an initial value.
When stepping through the code:
I can see the initial value
My function changes the value
When I use the variable later it has the wrong value
What is happening?
Note: this is intended as a reference question for common problems. If the generic answers here don't help you, post a question containing your complete, actual code.
There are several reasons why a variable might not keep a value. While some are arcane and difficult to debug, some of the most common reasons include:
The variable is modified by an interrupt
//---in main()---
unint8_t rxByte = 0;
printf("%d", rxByte); //prints "0"
//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG; //rxByte set to (for example) 55
//---later in main()---
printf("%d", rxByte); //still prints "0"!!!
If a variable is modified by an interrupt handler, it needs to be declared volatile. Volatile lets the compiler know that the variable could be modified asynchronously and that it shouldn't used a cached copy in a register.
//---in main()---
volatile unint8_t rxByte = 0;
printf("%d", rxByte); //prints "0"
//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG; //rxByte set to 55
//---later in main()---
printf("%d", rxByte); //corectly prints 55
Overrunning an array's bounds
There are no checks in C to prevent you from going beyond the bounds of an array.
int array[10];
int my_var = 55;
printf("%d", my_var); //prints "55"
for(i=0; i<11; i++) // eleven is one too many indexes for this array
{
array[i] = i;
}
printf("%d", my_var); // prints "11"!!!
In this case, we go through the loop 11 times, which is one index bigger than the array. In most compilers, this will result in overwriting variables declared after the array (anywhere on the page, they don't even have to be declared on the next line). This scenario can occur in many different circumstances, including multi-dimensional arrays and stack corruption.
Forgetting to dereference a pointer
While trivial, forgetting the asterisk on a pointer when making assignments will not set the variable correctly
int* pCount;
pCount = 10; //forgot the asterisk!!!
printf("%d", *pCount); //prints ??
Masking a variable with the same name
Reusing a variable name in an inner scope (like inside an if/for/while block or inside a function) hides a variable with the same name elsewhere.
int count = 10; //count is 10
if(byteRecevied)
{
int count = U0RXREG; //count redeclared!!!
DoSomething(count);
printf("%d", count); //prints "55"
}
printf("%d", count); //prints "10"
I'd like to add another possible reason to Zack's excellent answer.
Optimisation
This one frequently surprises me. A good optimising compiler will notice when two different variables are never used at the same time, and will optimise the program by giving those variables the same address in memory. When you are stepping through the code, you may see a variable apparently changing in the watch window. But what's really happening is that the variable that shares its address is being written to.
The other trick the compiler pulls is simply getting rid of a variable that it realises isn't necessary. Sometimes you might be doing the equivalent of this in your code:
force_a = mass_a * acceleration_a
force_b = mass_b * acceleration_b
total_force = force_a + force_b
The compiler sees that there's no real need for the variables force_a and force_b, and so changes the code to this:
total_force = (mass_a * acceleration_a) + (mass_b * acceleration_b)
You'll never see force_a and force_b being updates, but you'll still be able to add them to the watch window.
When I step through my program, I'm convinced that some variable or other has the wrong value in it, but when I let my program run through without stepping, it seems to work. Check that this isn't happening to you.
Added:
As Ashish Kulkarni mentioned, you can check this by turning off optimisation.