#include <stdio.h>
int a;
void myproc()
{
int a = 2;
while (a == 2)
{
int a = 3;
printf("a = %d\t", a);
break;
}
printf("a = %d\t", a);
}
int main()
{
a = 1;
myproc();
printf("a = %d\t", a);
return (0);
}
I expected the above code to print: a = 3 a = 3 a = 1
However, it prints: a = 3 a = 2 a = 1 Can someone please provide a valid explanation?
Here is an explanation -- see the commentary below.
#include <stdio.h>
int a;
void myproc()
{
int a = 2; // (1) a = 2
while (a == 2) // true
{
int a = 3; // (2) new scope, new a = 3
printf("a = %d\t", a); // (X) prints 3 as it gets the 'nearest a' in the scope
break;
} // throws away a=3 from (2)
printf("a = %d\t", a); // (Y) Uses (1) i.e. 2 and print it
}
int main()
{
a = 1;
myproc();
printf("a = %d\t", a); // (Z) Just prints 1 as the scope is not effected by myproc
return (0);
}
So this will print (X) (Y) and (Z)
i.e. 3 2 1
Yes, they are local automatic variables and are pushed on and popped off the stack when you enter and exit a given scope unless the compiler decides to make certain optimizations (such as storing them in registers, etc.) But for a given variable, the most locally scoped version of that variable is used when accessing it. For instance, in C89 should you decide to declare your loop counters within a for-loop declaration, the following typically produces a compiler error:
for (int i=0; i < N; i++)
for (int i=0; i < J; i++)
printf("%d", i);
The value of i printed will always be the value of i declared in the inner for-loop, since that is the most locally scoped version of i.
"Within a loop"?
The question you are asking has absolutely no relation to any loops at all. There's no difference between what you have in your code and the ordinary
int a;
void myproc()
{
int a = 2;
{
int a = 3;
printf("a = %d\t", a);
}
printf("a = %d\t", a);
}
Each nested block has it own variables. That's all there is to it. And it has nothing to do with any loops.
The declaration that is really related to the loop would be the declaration made in the header of the loop, as in
int a = 3;
for (int a = 0; a < 10; ++a)
{
...
}
printf("a = %d\n", a); // <- prints `3`
That a declared in the for header is still local to the loop.
The { } variables declare scope. As when you declare a variable between those braces it is only available in those braces. If you have nested variables (like in myproc you declare a = 2 and then inside the loop a=3) then the variable declared closet to the current scope is the one referenced (in the example, a = 3).
Since your print statements are nested in the {} only the most recently declared variable a is printed, getting your results.
Whenever you declaring a variable inside a loop, which is not available outside (out of scope for that variable ). So in your code
void myproc()
{
int a = 2;
while (a == 2)
{
int a = 3;// This is not accessable to outside while loop.
printf("a = %d\t", a);
break;
}
printf("a = %d\t", a);
}
If you want to print 3, 3, 1 remove int inside while loop :)
Actually, the loop is a significantly convenient obfuscator here.
Consider the while loop's test. This test is run twice during the execution of the program, and the first time the test succeeds, as the a it is examining has the value 2. The second time it is run, the test fails, because the a it is testing is a different a, which hold the value 3! This is very surprising.
Given my colleagues explanations, the three declarations of a exist in only their enclosing '{' and '}' delimited scopes (or the world scope for the first one). If this were literally true, then the while (a == 2) test should pass forever, as the interior a declaration assigned to the value 3 is completely hidden from it by the '{' and '}'
int a = 1; // world scope - a is 1
myproc()
{ // New scope; can define names inside here
int a = 2; // Redefine a to be 2
while ( a == 2 ) // We test whether a is 2
{ // New scope; can define names inside here
int a = 3; // Redefine a to be 3
} // end of scope, the a = 3 disappears; also branch back to top of loop
} // end of myprog scope, so the a=2 disappears
The way to understand this is to realize that the while (test) { statements; } is actually implemented as:
if ( test ) { // T1
L1: {
statements;
if ( test ) // T2
goto L1;
}
}
and so in truth, the test statement is replicated, and the first one 'T1' is executed in the scope outside of the '{' and '}' and gets the a that is 2, and passes; and the second one 'T2' is executed inside the scope of the '{' and '}' and gets the a that is 3 and the test fails.
Given your statements, the second test uses its locally scoped definition of a which is 3, so the loop is exited after one pass.
Related
I am having trouble coming up with a working helper function for my main, I believe the problem with my main program not working is because of this helper function.
its is supposed to loop through an array and see if there is an empty frame, i.e. an element that equals 1.
i have an array like this
int freeFrames[8] = {0, 1, 1, 1, 1, 1, 1 , 1};
and the helper function like this
int findEmptyFrame(int freeFrames[])
{
int i, index;
for(i = 1; i < 8; i++)
{
printf("FreeFrame = %d\n",i); // simple print statment
if(freeFrames[i] == 1){
index = i;
return index;
}
else{
return -1;
}
}
}
when I loop thru the array in my main Program it only ever reaches the 1st frame and returns it and doesn't ever cycle thru the next next element besides the first one
this is the section in my main where i am calling the function
else{
x = findEmptyFrame(freeFrames);
printf("X IS %d\n",x );
if(x > 0){
printf("IN IF BEFORE findEmptyFrame\n");
PT[pageNumber].fNum = x;
PT[pageNumber].vi = 0;
frameNumber = PT[pageNumber].fNum;
PA = (frameNumber << d) + dNum;
fwrite(&PA,sizeof(unsigned long), 1, myWriteFile);
printf("The Logical Address is at %lx and Translated Physical Addres is at %lx\n",LA, PA);
lruCount[frameNumber] = clock;
reverseMap[x] = pageNumber;
}
and an example of what i am currently getting is something like this
IN IF BEFORE findEmptyFrame
The Logical Address is at b70 and Translated Physical Addres is at f0
FreeFrame = 1
X IS 1
The reason this is happening is because in your for loop, if the freeFrame[i] is not equal to 1, the if condition fails. It therefore goes to the else part and returns -1. Therefore, you cannot return -1 within the for loop. You have to return it outside, like below:
int findEmptyFrame(int freeFrames[])
{
int i, index;
for(i = 0; i < 8; i++)
{
printf("FreeFrame = %d\n",i); // simple print statment
if(freeFrames[i] == 1){
freeFrames[i] = 0; //Change here
return i;
}
}
return -1;
}
What this does is, if there is a 1 in the array, it returns the index. If not, the whole for loop ends and only then it returns -1.
Also, indexing in the for loop must start from 0.
If you want the first free frame to be marked used, you additionally have to do that before returning the index. Check the change in code.
I am trying to understand how to use recursion in C, and I can't get how return works in it.
Please consider the following code:
int recur(int i)
{
printf("recur: i = %d\n", i);
if (i < 3)
{
recur(i + 1);
return 10;
}
else if (i < 5)
recur(i + 1);
return i;
}
int main(void)
{
int i = 0;
i = recur(i);
printf("i = %d\n", i);
return 0;
}
The output is:
recur: i = 0
recur: i = 1
recur: i = 2
recur: i = 3
recur: i = 4
recur: i = 5
i = 10
What does the last return, return i, do? Does this code even make sense?
The recursive calls of the function do not influence on the returned value. Only the first return met in the first instance of your recursive function will return a value to the parent function. Any other return met will just stop the function's instance the program is currently in.
Thus as the function was called in main with the argument 0
int i = 0;
i = recur(i);
The first return met is located inside of an if statement:
if (i < 3)
{
recur(i + 1);
return 10;
}
In this case, the recur function is called before returning a value to main. It will create another instance of recur which will do some stuff, but after this instance of recur has ended, the main instance of recur will continue and, in this case, will return 10 to the function main.
To know what your recursive function will return to the main function, you can simply comment all calls to a new instance of the function:
int recur(int i)
{
if (i < 3)
{
//recur(i + 1);
return 10;
}
else if (i < 5)
{
//recur(i + 1);
}
return i;
}
In this case, this is what the program will read:
int recur(int i)
{
if (i < 3)
return 10;
return i;
}
I think this is one of the easiest recursive function to understand.
int pow(int n, int x)
{
if (n != 1)
return x * pow(n - 1, x)
else
return x;
}
Let's study pow(3, 2) : 2^3 = 2 * 2 * 2 = 8
First iteration : pow(3, 2) returns 2 * pow(2, 2)
Second iteration : pow(2, 2) returns 2 * 2* pow(1, 2)
Third iteration : n == 1 so pow(1, 2) returns x = 2 * 2 * 2 = 8
A recursive function returns a call to itself at the i + 1 step of the process. In order to avoid an infinite loop, you have to make sur you have a break condition, which leads to a return to something different from a self-call.
You got at least one answer which helpfully explains the behaviour of your code.
I want to provide help via a different, additional path here. Both together provide different view points for you.
For that purpose I provide a version of your code augmented by instrumentation, which tells you more verbosely what happens.
This allows you to play with the code and observe, that will give you the really helpful answer.
Note:
the for(c lines are only for suggestive indentation;
I chose not to use a function for this, feeling that it keeps the interesting function calls more prominent
I added a parameter "nesting", it is for
making a part of the (hopefully useful) output
show that usually the recursive nesting has some influence
I introduced a local variable "j",
to show what happens with the reutrn values in most cases
Code:
#include <stdio.h>
int recur(int i, int nesting)
{ int c;
for(c=0;c<nesting;c++) { printf(" ");}
printf("recur[%d](%i)", nesting, i);
if (i < 3)
{ printf("i <3, calling recur[%d](%d)\n", nesting+1, i+1);
recur(i + 1, nesting+1);
for(c=0;c<nesting;c++) { printf(" ");}
printf("returning 10 from recur[%d], with i==%d\n", nesting, i);
return 10;
}
else if (i < 5)
{
int j=0;
printf("i <5, calling recur[%d](%d)\n", nesting+1, i +1);
j=recur(i + 1, nesting+1);
for(c=0;c<nesting;c++) { printf(" ");}
printf("ignored return value from recur[%d](%d) is %d", nesting+1, i+1, j);
}
printf("\n");
for(c=0;c<nesting;c++) { printf(" ");}
printf("returning i from recur[%d], with i==%d\n", nesting, i);
return i;
}
int main(void)
{
int i = 0;
i = recur(i, 0);
printf("the last return value did not get ignored: i = %d\n", i);
return 0;
}
Output:
recur[0](0)i <3, calling recur[1](1)
recur[1](1)i <3, calling recur[2](2)
recur[2](2)i <3, calling recur[3](3)
recur[3](3)i <5, calling recur[4](4)
recur[4](4)i <5, calling recur[5](5)
recur[5](5)
returning i from recur[5], with i==5
ignored return value from recur[5](5) is 5
returning i from recur[4], with i==4
ignored return value from recur[4](4) is 4
returning i from recur[3], with i==3
returning 10 from recur[2], with i==2
returning 10 from recur[1], with i==1
returning 10 from recur[0], with i==0
the last return value did not get ignored: i = 10
Note:
The recur[n](m) is of course no C syntax.
It just indicates a call to the function "recur" on nesting level "n" with parameter "m".
(Especially do not confuse the "[]" with arrays, they are not present.)
return 0 is the return from the main function, not from your recursive code.
Code snippet:
void function(void)
{
while(1)
{
int i = 0;
i += 1;
if(i == 500) break;
}
}
The variable i is stored in stack every time when restart the loop ?
What is the memory structure when running this code ?
What is the behavior of this variable ?
It is a bad or good practice do this ?
Thanks.
You will never reach i == 500. It's being reset every time through the loop since it's within the scope of while(1){}.
The following will work.
void function(void)
{
int i = 0;
while(1)
{
i += 1;
if(i == 500) break;
}
}
When a function runs in C, it allocates space for all the local variables its going to need. If the variables are allocated all next to each other at the top of the function its easy to see how it works:
void foo(){
int x;
int y;
y = 1;
x = y + 2;
return x + y;
}
If the variables are declared inside inner blocks of the function, what the compiler does is "lift" those variable declarations to the top of the function. If there are variables with clashing names, the compiler renames things for you so they reference the correct variable.
// This is what you write
void original(){
int x = 0;
while(1){
int x = 1;
}
}
// This is what the compiler "sees"
void lifted(){
int x1;
int x2;
x1 = 0;
while(1){
x2 = 0;
}
}
In your case, your code is behaving like this one:
void function(void)
{
int i;
while(1)
{
i = 0;
i += 1;
if(i == 500) break;
}
}
In this version, its clear that the i is being reset to 0 all the time, which is why the loop will run forever.
As for if declaring variables in inner scopes is a good practice or not, it doesn't have to do with memory usage but with the scope of your variable names. In general its a good thing to keep your variables confined to inner scopes if possible (for the same reason why local variables are preferred to global ones). That said, you always have to initialize your variables before the loop and not inside it. In this case, its about removing bugs and not about being a best practice.
Logically speaking, each iteration of the loop creates a new instance of the i variable which only exists within the body of the loop. As written, this code will never terminate, because each iteration of the while loop creates a new instance of i and initializes it to 0.
Attempting to reference i outside the body of the loop results in undefined behavior; IOW, code like
int *p;
while ( 1 )
{
int i = 0;
p = &i;
if ( some_condition )
break;
...
}
printf( "last value of i was %d\n", *p );
isn't guaranteed to do what you expect.
In practice, the generated machine code will set aside the space for i once at function entry; however, you should not rely on that behavior.
The variable i will always be at 0 or 1 in this code; the break will never execute.
The variable i is declared in and is local to the while loop.
In the C language, a pair of braces can create a new scope
that hides variables with the same name declared outside the
scope.
This code:
void function(void)
{
while(1)
{
int i = 0;
i += 1;
if(i == 500) break;
}
}
should be changed to this:
void function(void)
{
int i = 0;
while(1)
{
i += 1;
if(i == 500) break;
}
}
I would like to display the output - numbers 1 to 5, followed by 4-5 infinitely. Is there any way i can pass the value of i(4) instead of the character i in goto1. Or is there any other efficient way of realizing this without illustrating all the options as in switch(i.e case 1: goto1(c1) ,etc..).
The main aim is to jump to a statement whose label is computed within the program.
#define goto1(i) \
goto c##i
int main(){
c1 : printf(" num is 1 \n");
c2 : printf(" num is 2 \n");
c3 : printf(" num is 3 \n");
c4 : printf(" num is 4 \n");
c5 : printf(" num is 5 \n");
int i=4;
goto1(i);
}
If you are ... adventurous (or do I mean silly?), you can use a GCC extension Labels as Values.
6.3 Labels as Values
You can get the address of a label defined in the current function (or a containing function) with the unary operator ‘&&’. The value has type void *. This value is a constant and can be used wherever a constant of that type is valid. For example:
void *ptr;
/* ... */
ptr = &&foo;
To use these values, you need to be able to jump to one. This is done with the computed goto statement1, goto *exp;. For example,
goto *ptr;
Any expression of type void * is allowed.
One way of using these constants is in initializing a static array that serves as a jump table:
static void *array[] = { &&foo, &&bar, &&hack };
Then you can select a label with indexing, like this:
goto *array[i];
Note that this does not check whether the subscript is in bounds—array indexing in C never does that.
Such an array of label values serves a purpose much like that of the switch statement. The switch statement is cleaner, so use that rather than an array unless the problem does not fit a switch statement very well.
Another use of label values is in an interpreter for threaded code. The labels within the interpreter function can be stored in the threaded code for super-fast dispatching.
You may not use this mechanism to jump to code in a different function. If you do that, totally unpredictable things happen. The best way to avoid this is to store the label address only in automatic variables and never pass it as an argument.
An alternate way to write the above example is
static const int array[] = { &&foo - &&foo, &&bar - &&foo,
&&hack - &&foo };
goto *(&&foo + array[i]);
This is more friendly to code living in shared libraries, as it reduces the number of dynamic relocations that are needed, and by consequence, allows the data to be read-only.
The &&foo expressions for the same label might have different values if the containing function is inlined or cloned. If a program relies on them being always the same, __attribute__((__noinline__, __noclone__)) should be used to prevent inlining and cloning. If &&foo is used in a static variable initializer, inlining and cloning is forbidden.
Footnotes
[1] The analogous feature in Fortran is called an assigned goto, but that name seems inappropriate in C, where one can do more than simply store label addresses in label variables.
Under no circumstances should this be taken as a recommendation to use the feature. The computed goto was eventually removed from Fortran; it is best left in the dustbin of history.
Are you asking for a jump table? If you are using gcc: It has a jump table mechanism.
#include <stdio.h>
int main()
{
unsigned char data[] = { 1,2,3,4,5,4,5,0 };
// data to "iterate" over, must be 0-terminated in this example
void *jump_table[] = { &&L00, &&L01, &&L02, &&L03, &&L04, &&L05 };
// you should fill this with all 256 possible values when using bytes as p-code
unsigned char *p = data;
begin:
goto *jump_table[ *p ];
L00:
return 0; // end app
L01:
printf("num %i\n", (int)*p);
goto next;
L02:
printf("num %i\n", (int)*p);
goto next;
L03:
printf("num %i\n", (int)*p);
goto next;
L04:
printf("num %i\n", (int)*p);
goto next;
L05:
printf("num %i\n", (int)*p);
goto next;
L06:
L07:
// ...
LFF:
goto next;
next:
++p; // advance the data pointer to the next byte
goto begin; // start over
return 0;
}
The pro about this method is that you spare the large switch statement.
Since you want to do this the wrong (aka. creative) way, have you considered trampolining?
#include <stdio.h>
typedef void (*generic)(void);
typedef generic (*continuation)(void);
generic first(void);
generic second(void);
int main(void) {
continuation fubar = first;
for (;;) {
fubar = (continuation) fubar();
}
}
generic first(void) {
printf(" num is 1 \n"
" num is 2 \n"
" num is 3 \n");
return (generic) second;
}
generic second(void) {
printf(" num is 4 \n"
" num is 5 \n");
return (generic) second;
}
Continuing on from the idea of using function pointers (see what I did there? Giggity!), you could use an array of function pointers:
#include <stdio.h>
typedef size_t (*function)(size_t);
size_t first(size_t);
size_t second(size_t);
int main(void) {
function function[] = { first, first, first, first, second };
size_t index = 0;
for (;;) {
index = function[index](index);
}
}
size_t first(size_t index) {
printf(" num is %d \n", ++index);
return index;
}
size_t second(size_t index) {
printf(" num is %d \n", index+1);
return index-1;
}
Why not do it like this?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf(" num is 1 \n");
printf(" num is 2 \n");
printf(" num is 3 \n");
for (;;){
printf(" num is 4 \n");
printf(" num is 5 \n");
}
/* Not reachable, but will silence any compiler warnings about main
* not returning a value. */
return EXIT_SUCCESS;
}
Wouldn't a switch accomplish the same thing?
int main()
{
int i = 1;
while (1)
{
switch (i)
{
case 1:
printf(" num is 1 \n");
case 2:
printf(" num is 2 \n");
case 3:
printf(" num is 3 \n");
case 4:
printf(" num is 4 \n");
case 5:
printf(" num is 5 \n");
default:
break;
}
// code to calculate i
i = 4;
// end code to calculate i
}
return 0;
}
Simple Question. Imagine this in ANSI-C:
int i;
for(i=0 ; i<5 ; i++){
//Something...
}
printf("i is %d\n", i);
Will this output "i is 5" ?
Is i preserved or is the value of i undefined after the loop?
Yes. If i is declared outside of the for loop it remains in scope after the loop exits. It retains whatever value it had at the point the loop exited.
If you declatred I in the loop:
for (int i = 0 ; i < 5 ; i++)
{
}
Then i is undefined after the loop exit.
Variable i is defined outside of the scope of the loop (which is great, or you wouldn't be able to print it in that case).
And it is post-icnremented for every-turn of the loop, for which the end condition is "stop when i is bigger or equal to 5".
So it really makes perfect sense for i to be equal to 5 at this point.
A block scope is not exactly the same as a function scope in C. The variable i doesn't "get back" magically to its previous value when you step out of the loop's scope.
i's value will be 5 after your loop. Unless you did something like
i = 50000;
inside of it.
It's also generally recommended against using "i" after you exit the loop in most coding standards I have ever read. In particular do NOT do:
for(i = 0; i < num_elements; i++)
{
if(element[i].id == id)
{
/* Do something to element here. */
break;
}
}
if(i == num_elements)
{
fprintf(stderr, "Failed to find element %d.", id);
succeeded == false;
}
While this will work it is poor coding. It is less readable and maintainable than the alternatives. E.g.
succeeded = false;
for(i = 0; i < num_elements; i++)
{
if(element[i].id == id)
{
/* Do something to element here. */
succeeded = true;
break;
}
}
if(false == succeeded)
{
fprintf(stderr, "Failed to find element %d.", id);
}
Yes, variables are valid only inside the block in which they are declared.
Here's an example:
#include <stdio.h>
void main(int argc, char *argv[])
{
if(argc == 2) {
int x;
x = 7;
}
x = 1;
}
That's the compiler:
gcc ex.c
ex.c: In function ‘main’:
ex.c:10: error: ‘x’ undeclared (first use in this function)
ex.c:10: error: (Each undeclared identifier is reported only once
ex.c:10: error: for each function it appears in.)