Understanding For loop in C - c

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;

Related

Enter unknown number of array values in C/C++ has strange behaviour

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

Why did the compiler assign different memory address to the same variable, after re-defining the variable?

The code is as follows:
#include <stdio.h>
int main()
{
int i;
printf("%p\n",&i);
for (i = 0; i < 5; i++)
{
int i = 10;
printf("%d %p\n", i,&i);
i++;
}
return 0;
}
First we defined a variable i (just after main). Then at the start of for loop we defined the same variable i again. So, inside for loop, value of i is 10. The for loop must iterate only once, since i>5 after first iteration. But to my surprise the output is as follows:
0x7ffe8b799da0
10 0x7ffe8b799da4
10 0x7ffe8b799da4
10 0x7ffe8b799da4
10 0x7ffe8b799da4
10 0x7ffe8b799da4
My questions are:
1) Why is the compiler considering the initial defined variable i while executing i<5;i++ instruction and, not the re-defined variable i? (after first iteration).
2) Why did compiler assign different memory address to same variable identifier i?
Why is the compiler considering the initial defined variable i while
executing i<5;i++ instruction and, not the re-defined variable i?
(after first iteration).
Because the re-defined (shadowing) variable isn't in scope yet. If you remove the first definition, you get an "identifier undeclared" error. This also doesn't change after the first iteration of the loop as it is determined at compile time.
2) Why did compiler assign different memory address to same variable
identifier i?
Even though you can't access the outer int i inside the loop as the second one shadows it, it still exists and therefore needs its own memory. It's not overwritten by the other int i. You can see that by putting a printf("%d\n", i); after the loop - it will print 5, because that's the value of that i after loop.
On another note, the i++; at the end of the loop has no effect because it affects the i inside the loop, which goes out of scope right after the i++;. This is unlike the i++; in the for (i = 0; i < 5; i++), which increases the outer i.
You've got two different variables both named i, so obviously the situation is going to be confusing! For every i in the program, we have to ask: is this the "outer" i, or the "inner" i?
Here's your program again, with the variables renamed for clarity:
#include <stdio.h>
int main()
{
int i1;
printf("%p\n",&i1);
for (i1 = 0; i1 < 5; i1++)
{
int i2 = 10;
printf("%d %p\n", i2,&i2);
i2++;
}
return 0;
}
To your specific question, the reason the loop runs 5 times is that the loop control for (i = 0; i < 5; i++) is unquestionably using the outer i.

this is a program to find prime numbers from 2 to 100 in C [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am unable to understand how is it working. Can somebody explain me this code?
#include <stdio.h>
int main () {
/* local variable definition */
int i, j;
for(i = 2; i<100; i++) {
for(j = 2; j <= (i/j); j++) {
if(!(i%j)) break; // if factor found, not prime
}
if(j > (i/j)) printf("%d is prime", i);
}
return 0;
}
1.#include <stdio.h> is a header that defines three variable types, several macros, and various functions for performing input and output. In other words, it's basically a C-Library being referenced to add some other externally defined logic, besides the code below, like the size_t variable, which is the result of the sizeof keyword for example. That's just one example of what the the stdio.h header does but you can see more info here: https://www.tutorialspoint.com/c_standard_library/stdio_h.htm
2.int main() is an integer function (int) that uses a deprecated declaration style main(), meaning you shouldn't it anymore because it's outdated by other functions, and the main() function in particular is a function that takes an unspecified number of arguments (integers in this case) and then runs some operations with those integers.
Next, the curly braces are what contain all the logic inside of the int main() function. Then inside of it, on the line int i, j; , two local variables are declared (i and j) to be later used as placeholders for some integers that will be plugged into the function.
Below that, for(i = 2; i<100; i++) indicates there is a loop that sets the i variable to 2, then after the semi-colon i<100 means that the loop will continue to execute again and again as long as the variable i is less than 100. After yet another semi-colon, i++ means that each time that the loop runs, the variable i will increment by 1. So it starts at 2, then 3, then 4, etc, until i reaches 100 and the loop stops executing.
Next, for(j = 2; j <= (i/j); j++) is another loop inside of the first loop, but this time the loop is using the variable j as a placeholder/counter instead of the variable i (the variable used by the previous loop), which surrounds this loop starting with "for(j..." . This loop also setsj to 2 (the same way the surrounding loop set i to 2); as long as j is less than or equal to (i divided by j) the loop will continue to execute; and j will increment (increase) by one each time that the loop is run, the same way that i does in the loop that surrounds this one.
if(!(i%j)) break; // if factor found, not prime this line means that the loop will also stop executing (break) if the remainder of i divided by j does not equal zero.
if(j > (i/j)) printf("%d is prime", i); This line means that if j is greater than i divided by j that the loop will write/output the text to stdout (std out is the standard output device, a pointer to a FILE stream that represents the default output device for the application).
Lastly, the last return 0; line indicates a return from the function and the final curly brace encloses the functions logic/code. The main function also should return 0(also EXIT_SUCCESS) to identify that the program has executed successfully and -1 otherwise (also EXIT_FAILURE).
Additional Note - Loops in every programming language I've seen personally tend to have a few things in common:
i. An init counter, a value where the loop will initialize (start counting), inside the loop's parentheses and before the first semi-colon.
ii. A test counter, which will be evaluated each time that the loop continues, and if it evaluates to TRUE the loop will continue usually but if it evaluates to false then the loop will end. This is the part of the loop after the first semi-colon but before the second semi-colon.
iii. An increment/decrement counter, which increases or decreases the loop by some value each time that the loop is run. This is the part of the loop inside the parentheses, after the second semi-colon. If there is no increment counter or test counter that causes the loop to exit/break at some point, then this is known as an infinite loop. This is a very bad thing in programming because it will cause just about any computer program to crash since it will execute and consume computing resources indefinitely. Not good :)
Disclaimer: I don't actually code in C but the language has so many similarities with programming languages I do use, that I'm guessing this answer is very close if not 100% correct. Curious to hear some input from an expert C programmer though!
Your code is looping over all integers from 2 to 99, holding the actual number in i.
for(i = 2; i<100; i++)
Then, for every number i, the code is looping again over all integers from 2 to (i/j).
for(j = 2; j <= (i/j); j++)
Your loop's finishing condition is mathematically equivalent to j being smaller than the square root of i, since any larger integer j would already contain itself a smaller factor of i.
(To check this, get a paper and rewrite the inequality so hat i is the sole part of the right hand side of your condition.)
Then it checks whether or not j divides i.
(i%j)
If j is a factor of i, then i modulo j is zero and hence
if (!(i%j))
evaluates to true (since 0 is evualted as false and ! negotiates this) and you can break out of the loop since i has a divisor not being 1 or i, hence i is not a prime.
On the other hand, if the inner loop is finished, you have found a prime since it has only 1 and i as divisor.
Needles to say that this bruteforce approach is very slow for large integers (you won't crack RSA with that), but does this clarify your questions?
#include <stdio.h>
int main () {
/* local variable definition */
int i, j;
// Loop from 2 to 99; i will hold the number we are checking to
// see if it is prime
for(i = 2; i<100; i++) {
// now loop through the numbers checking each one to see if
// it is a factor of i (if it is, then i isn't prime). This
// loop stops when j^2 is greater than or equal to the number
// we are checking
for(j = 2; j <= (i/j); j++) {
// i % j (i modulus j) is 0 iff j is a factor of i. This
// if test relies on the fact that 0 is false in C (and
// all nonzero values are true)
if(!(i%j)) break; // if factor found, not prime
}
// this tests to see if we exited the above loop by failing
// the test in the for() statement, or whether we exited the
// loop via the break statement. If we made it through all
// iterations of the loop, then we found no factors, and the
// number is prime.
//
// note that a \n is missing at the end of the printf format
// string. The output will be "2 is prime3 is prime5..."
if(j > (i/j)) printf("%d is prime", i);
}
// returns from main() with a value of 0, which will result in
// the program exiting with an exit code of 0. An explicit
// exit(0) is better form here, but this is not incorrect.
return 0;
}

what's the difference between these two in C?

in learning quick union algorithm, i have met these two statements
for(i=p; i!=id[i]; i=id[i]);
for(j=q; j!=id[j]; j=id[j]);
since I only learned for loop to be something like
for(i=0; i<100; i++)
I don't know the difference between the two statements and the following statements
i=p; i=id[i];
j=q; j=id[j];
i have no idea why the results are different?
thanks
I want to ask why
#include <stdio.h>
#define N 10000
int main()
{
int i, j, p, q, id[N];
for(i=0; i<N; i++) id[i]=i;
while(scanf("%d %d\n", &p, &q)==2)
{
for(i=p; i!=id[i]; i=id[i]);
for(j=q; j!=id[j]; j=id[j]);
if(i==j) continue;
id[i]=j;
printf(" %d %d\n", p, q);
}
}
is different from
#include <stdio.h>
#define N 10000
int main()
{
int i, j, p, q, id[N];
for(i=0; i<N; i++) id[i]=i;
while(scanf("%d %d\n", &p, &q)==2)
{
i=p; i=id[i];
j=q; j=id[j];
if(i==j) continue;
id[i]=j;
printf(" %d %d\n", p, q);
}
}
I have tested the results, that's why I am confused
i=p;
Sets i to the value of a variable p (defined and initialized elsewhere in the program)
i=id[i]
Sets i to the value of the i th element of the array id (defined and initialized elsewhere in the program)
for(i=p; i!=id[i]; i=id[i]);
Loop initializes i to the value of p, executes the statements inside the for loop once if i is not equal to the i'th value of the array id, and then stops.
Further explaination:
assuming some values for the variables:
int p = 4;
int i;
int id[5] = {1,2,3,4,5};
for(i=p; i!=id[i]; i=id[i]) {
printf("Loop executed!\n");
}
Output:
Loop executed!
And then a segmentation fault.
What happens:
i is set to 4, then compared to id[4]. This is unequal, thus the loop is triggered. After that it sets i to 5. Now it tries to compare id[5] to i. This is disallowed because id only has space for 5 elements and indexes start at 0.
When looking at non-standard for "loops" like this, it helps to convert your for loops into while loops. (that is all they really are)
To do that, remember that a for loops consists of three parts separated by semicolons. The initialization part, the conditional part, and the update or increment part:
for(initialize statement; boolean loop conditional; update/increment statement);
The initialize statement is executed before your loop, the loop conditional is evaluated to determine whether the loop continues, and the update/increment statement is executed as the end of the loop.
Your first example:
for(i=p; i!=id[i]; i=id[i]);
As a while loop, looks like..
i = p
while(i!=id[i]) {
i = id[i];
}
Your second example:
for(j=q; j!=id[j]; j=id[j]);
As a while loop, looks like..
j = q
while(j!=id[j]) {
j = id[j];
}
Once they're written like this, it's easier to tell what's going on.
We're initializing the loop variable to one of two values, p or q.
Then, we're looking into the array "id" at the location specified by the loop variable and updating the loop variable with it. This has the effect of looking up in the array the next loop variable. In other words, each slot in the array contains the next value to jump to.
The conditional checks to see whether the destination is the same as the current location. That is to say, if we are "told" to jump to the location we're already in.
The difference between you two loops is only the initialization value. The first one initializes to p where the second initializes to q.
It may be helpful to manually jump through a simple cases such as..
p=0
q=1
id = {1,2,2}
p=2
q=1
id = {0,0,2}

How many temporary variables are created in this loop?

for(i = 0; i < 5; i++){
int j;
printf("%X\n", &j);
}
How many temporary variables j are created in this loop?
Is j created 5 times, or only once?
Though the address is the same..
5. Although the compiler could certainly optimize that to 1.
Suppose you modified your code slightly:
for (i = 0; i < 5; i++)
{
int j = rand();
printf("%5d (%p)\n", j, (void *)&j);
}
You would see a different value for j in each iteration, making it clear that j is given a value each time through the loop, even if the address of j was the same in each loop. This would demonstrate more clearly that j is initialized on each iteration (and is logically created and destroyed on each iteration).
Well, there are two things to mention here,
Locality of a Variable:
The locality of the variable j is the next '}'. When the program approaches the bracket, the variable j dies.
Temporal Locality:
There is a mechanism in computers that they tend to keep the extensively used variables and prevent them from dying because they might be needed again. So it is very much possible that the computer will in real not generate the variable j 5 times.
Conclusion:
As far as the answer to your question is concerned so you can say 5 as the person who wanted asked you this question wanted you to get an idea about locality of a variable.

Resources