Code:
#include<stdio.h>
int main(void)
{
int i, j;
for(j = i+1, i=1; i<=5; j++, i++)
printf("%d %d\n", i, j);
return 0;
}
Output:
1 66
2 67
3 68
4 69
5 70
Can Anyone explain about the nature of output of the code?
i is unitialized when you set j=i+1. So j (initially) could be almost anything.
In your code i, j are not initialized at the time of declaration.
In for loop you assign j = i + 1 So j remains garbage value whereas i assigned 1 ,
in for loop you increment i, j and printf values. i increment from 1 to 5, and j from a initial garbage value (that is 66 in your output) to initial garbage + 5.
Edit On the basis of comments:
If you don't assign an initial value upon declaration the variable will be pointing at an address that may contain previously used data from another application(or any last used).
Before allocating memory in runtime system does not clear the memory before allocating (just to keep system performance high) So,default value of the variable is garbage value.
j is assigned the value of i even before i is assigned = 1. So i here can be any arbitrary value provided to it by the OS. In the above case the value assigned to i by the OS was 66. This arbitrary value could be different on varying systems.
Related
I need to populate an array of integers with an unknown number of elements. I am using a while loop to input values and exit the loop as a non integer value is entered. Outside the loop an integer j is initialized at 0 and used to address array elements inside the loop. At each round of the loop I check the value of j before and after the input value is assigned to array element v[j], then j is incremented.
Depending on the size chosen for the array in the declaration, (in the example below v[8]), index j is unexpectedly affected by the assignment itself: in the example below when j equals 11 before the assignment it becomes 2 after the assignment, thereafter messing it all up. As a result the code fails to assign the correct input values to the array.
I am surely lacking some deeper knowledge about C/C++ array management... anyone can help to to fill the gap explaining the apparently strange behaviour of my code?
#include <stdio.h>
int main()
{
int j = 0, m, v[8];
printf("Enter an integer: to finish enter x\n");
while (scanf("%d", &m))
{
printf("j before assignment:%d - ", j);
v[j] = m;
printf("j after assignment:%d - ", j);
printf("v[j] after assignment:%d\n", v[j]);
j++;
}
return 0;
}
You write beyond the array boundaries of v. To avoid this, check j in a for loop, e.g. replace while (...) with
for (j = 0; j < 8 && scanf("%d", &m) == 1; ++j) {
// ...
}
This way, the loop stops after the end of the array (v[7]) is reached.
To comment the "strange" behaviour, read about stack and stack layout, e.g. Does stack grow upward or downward?
As always, check the C tag wiki and the books list The Definitive C Book Guide and List
Output of the program:
#include <stdio.h>
int main()
{
int size;
printf("Enter the size of array: ");
scanf("%d",&size);
int b[size],i = 0;
printf("Enter %d integers to be printed: ",size);
while(i++ < size)
{
scanf("%d",&b[i]);
printf("%d %d\n", i, b[i]);
}
return 0;
}
for size = 5 and input numbers :
0 1 2 3 4
is
1 0
2 1
3 2
4 3
5 4
where first column is for i and second for elements of array b.
It is clear that i in the loop while(i++ < size) { incremented to 1 before entering the loop. This loop should have to store/print the value at/of b[1], b[2], b[3], b[4] but not b[5] as loop will terminate at i = 5.
How this code is printing the value of b[5]?
I have tested it for different array size and it is not printing any garbage value.
By reading and writing past the array, your program invokes undefined behavior. It doesn't mean that it has to crash or print garbage values, it can pretend working fine. Apparently, that's what is happening in this case.
In your loop, the condition i < size is checked before i is incremented. But, i is incremented before entering the body of the loop and not after it, so it is possible to access b[5] in this case, as i would be incremented after checking i < size with i=4. You do not want that, as this causes undefined program behavior.
If you try to access an element in the array which does not exist, e.g. array[size], you are accessing the next spot in the memory right after the array. In this case you are lucky, but if this meant you were accessing a part of the memory where your program isn't allowed to do so, you'd get a segmentation fault.
you could use a for cycle instead of a while so instead of while(i++<size)you could use for(i = 0; i < size; i++) that should solve your problem my friend :)
I referred this, this and this SO posts before asking this question:
While teaching dynamic memory allocation to a friend, I wrote a simple program, whose snippet is below:
matrix = (int**) malloc (sizeof(int*) * m);
for (i = 0; i < m; ++i)
matrix[i] = (int*) malloc (sizeof(int) * n);
for (i = 0; i < m; ++i)
for (j = 0; j < n; ++j)
matrix[i][j] = rand() % 100; /*some random value*/
for (i = 0; i < m; ++i)
{
for (j = 0; j < n; ++j)
{
printf("(%8u)%-5d", &matrix[i][j], matrix[i][j]);
}
/* Print element just after the first row*/
printf("(%8u)%-5d", matrix[i] + n, *(matrix[i] + n));
/* Print second NEXT element just after the first row*/
printf("(%8u)%-5d", matrix[i] + n + 1, *(matrix[i] + n + 1));
}
When I run this program as
unmesh#unmesh-laptop:~/teaching/C/Day3$ ./matrix
Enter number of rows: 3
Enter number of columns: 3
(141189144)1 (141189148)2 (141189152)3 **(141189156)17** (141189160)2
(141189160)2 (141189164)3 (141189168)4 **(141189172)17** (141189176)3
(141189176)3 (141189180)4 (141189184)5 (141189188)135105(141189192)0
I am curious about the value 17. If I am not mistaking, there are three calls to malloc in this invocation, So memory may not be contiguous as can be observed.
But I run the program with m=n=4 or m=n=5, then I can see the value 25 after each row.
For m=n=6 and m=n=7, value 33 is observed.
More interesting is the fact that when n is odd (n=3 / n=5 ..) this value is stored immediately after the row ends.
example row when m=n=3
Values 1 2 3 17
Address 100 104 108 112
Next row starts from 116
When n is even, it is stored after 4 bytes
example row when m=n=2
Values 1 2 0 17
Address 100 104 108 112
Next row starts from 116
Question is where do these values 17/25/33 come from ?
Why are they always the same ? I hope they are not garbage and must have some meaning ..
I fail to deduce. Please help.
You're seeing the internal bookkeeping information malloc stores to keep track of blocks that have been allocated. The precise nature and size of this information varies from system to system, but it is often the case that malloc rounds up the size requested so that, when combined with its bookkeeping info, the resulting block is a multiple of the largest alignment generally required for your machine. In your case, it looks like the alignment is 8 bytes (two ints), leading to the even/odd behavior you see. The 17/25/33 values you see are likely the sizes of the allocated blocks (including the padding and size info) with the lowest bit set to indicate an in-use block.
I am having little difficulty in figuring out following piece of simple for loop code in C.
int j=20;
for(int i=0, j; i<=j ; i++, j--)
printf("i = %d and j = %d \n",i,j);
Prints output as
i=0 and j=2
i=1 and j=1
Why it does not starts with j=20 and rather prints j=2 and stops after j=1.
But when I use this code
int j=20;
for(int i=0, j=20; i<=j ; i++, j--)
printf("i = %d and j = %d \n",i,j);
It starts properly with
i=0 and j=20 upto ... i=9 and j= 11
Is there something that I am missing ?
You are. Declaring j inside of the for construct creates a new (scoped) j, which has a value different from the outer. If you fail to initialize it, you get whatever crap happened to be in memory when allocated.
Variables like this are called "automatic" variables, and are allocated on the program's stack. As you need one, more stack space is allocated. When they go out of scope (really when the function returns), they are cleaned up by popping them all back off.
When the next bit of automatic storage is needed, the same thing happens and you then get whatever bit pattern happened to be left over on the stack as your new variables value.
Note that in the first portion of the for loop you have done int i = 0, j. What this does is to declare a variable named j which has a scope local to the for loop . Therefore there is no relation between the j declared and defined before the for loop and the one which you declare and define inside the for loop scope. Referring j inside the loop will refer to the one which is the innermost block, therefore taking j initialized to zero you get the first output.
Also note that you are lucky enough that the value of j is zero. It is an automatic variable and is not guaranteed to be zero upon definition.
On the next loop you see the output you want because, as previously the j defined inside the for loop is referred, but as you have initialized the value of j local to the for loop with the same value of the j outside (which has nothing to do with the j inside the for loop), hence you get the second output in your question.
Basically this is the common confusion in for loop syntax. What happening in your case is:
int i=0, j; //create 2 int variables - i (which is initialized to 0) and uninitialized j
This looks similar to for(i,j; i<j; i++, j--). However what you did - is basically created additional uninitialized variable j.
This question is about one-line code.
when you type int i=0, j; in a line, it equals to int i = 0; int j;
however, when you type int i=0, j=20;, it will give you an error unless the j has defined before, it does not equals to int i = 0; int j = 20;
I am stuck with this mystery regarding for loop.
int abc[3], i, j;
for(j=0; j<3; j++);
printf("%d\n", j);
abc[j] = abc[j] + 3;
printf("%d \n", j);
Output:
3
6
Output should have been 3,3 as I've not changed value of j.
Adding 3 to the jth value of abc has resulted in change of value of j by 3. This happens only while exiting from a for loop and then trying to change the value of abc[j].
Maybe I am missing something pretty obvious. Any help would be much appreciated.
You have a buffer overflow since you declared your array to have size 3 int abc[3]; yet you are indexing the 4th element; this is Undefined Behavior.
abc[j] = abc[j] + 3; // j = 3 here, overflow
What you are most likely seeing is that j is located on the stack just past your array abc and so when you overflow one past the array with abc[3], you're actually modifying the memory that contains j.
*Note that nowhere in the C standard does it mention the word stack, this is an implementation detail and can change from system to system. This is partly the reason why it is Undefined Behavior and you are getting responses from people that they see two 3's as output.
You're indexing past the end of the array (buffer overflow) and reassigning other variables on the stack.
int abc[3], i, j;
// Your stack looks like this (single 'x' is one byte):
// |abc[0]|abc[1]| abc[2]| j | i |
//
// |xxxx |xxxx |xxxx |xxxx|xxxx|
//
for(j=0; j<3; j++);
printf("%d\n", j);
// j = 3 at this point
// abc[3] points past the end of the array abc, in this case, at j.
// So the next statement increments j by 3.
abc[j] = abc[j] + 3;
printf("%d \n", j);
To verify, try adding the following statements at the end:
printf("%d\n", &i == &abc[3]);
printf("%d\n", &j == &abc[3]);
EDIT
The exact layout of the stack will matter depending on the compiler you're using:
misha#misha-desktop:~/Desktop/stackoverflow$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
misha#misha-desktop:~/Desktop/stackoverflow$ ./a.out
3
3
Here's why it's working fine on my machine -- the statement:
printf("abc: %x abc[3]: %x i: %x j: %x\n", &abc, &abc[3], &i, &j);
gives the following output:
abc: 4cd0aa70 abc[3]: 4cd0aa7c i: 4cd0aa8c j: 4cd0aa88
So the stack is actually:
// aa70 aa74 aa78 aa7c aa88 aa8c
// |abc[0]|abc[1]| abc[2]| | .... | j | i |
So when it's accessing abc[3], it's accessing 0x4cd0aa7c which is just "dead space".
When J = 3, abc[j] refers to 4th element, since, array indexes begin with 0 and not 1. So, you are trying to access a location which is beyond the memory area of the array abc. Coincidentally this location happens to be that of J. Hence, value of J gets modified. Try changing the order of declaration of variables to better understand this behavior.
Thanks,
Vamyip
for(j=0; j<3; j++);
You have a semicolon at the end of the for loop. Problem solved.