Does For-Loop counter stay? - c

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.)

Related

error: control reaches end of non-void function [-Werror=return-type]|

I am trying to get from the while loop the counter value to the main block.
everything worked fine until I got the counter integer involved and now I'm getting this error:
"error: control reaches end of non-void function [-Werror=return-type]|"
What do I need to do to fix it? I want to get the counter value from the function into the main block to use it and print the actual value of it.
Thanks!
int ScanFunction(char array[ThirtyOne] , int counter){
PrintEnterMessage();
for(int i=0 ; i < ThirtyTwo ; i++)
{
scanf("%c" , &array[i]);
counter++;
if(array[i] == Fourtynine || array[i] == Fourtyeight) array[i] = array[i] - '0'; // This is to convert the numbers from char to int
if(array[i] == Excmark)
{
array[i] = 0;
return counter;
}
}
}
int main(){
char array[ThirtyOne] = {0};
int counter = -1;
ScanFunction(array, counter);
printf("%d, counter is: %d" , array[1], counter);
return 0;
}
ScanFunction() promises to return an int and it does so only if the second if block after if(array[i] == Excmark) gets hit. You need to add some other return at the end of the function, in order to return a value in the case that the if block is not reached.
Additionally, you do nothing with the value that gets returned by ScanFunction(). You need to assign some variable to the output of the function, such as:
counter = ScanFunction(array, counter);

Crash with no idea why

int procurarMatriculaLista(tipoEspera listaDeEspera[], int ClistaDeEspera, char matricula[])
{
int i, pos= -1;
for(i = 0; i<ClistaDeEspera; i++)
{
printf("coock");
if(strcmp(listaDeEspera[i].matricula, matricula) == 0)
{
pos=i;
i=ClistaDeEspera;
}
}
return pos;
}
It has no errors but my program crashes whenever I call this function. Why?
If it's crashing in that function, the most likely cause is that the arguments being given to strcmp are causing it to fail. Such as if they're not actually C-style strings, or if the length value (ClistaDeEspera) you're passing in is too big for the actual array.
Hence you need to check listaDeEspera[i].matricula where i ranges from 0 to ClistaDeEspera - 1 inclusive, and matricula.
Most likely one of those values is not what you think it is.
As an aside, your code could be made "cleaner" by getting rid of the store-position-and-force-loop-end aspect. With a small piece of code like this, multiple return points have no real detrimental affect on readability:
int procurarMatriculaLista(tipoEspera listaDeEspera[], int ClistaDeEspera, char matricula[]) {
for (int i = 0; i < ClistaDeEspera; i++)
if (strcmp (listaDeEspera[i].matricula, matricula) == 0)
return i;
return -1;
}

Variable scope behavior c language

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;
}
}

Function Warnings in C

Hello guys i have threefunctions for which i get 4 warnings...!!
The first one is this
void evaluatearxikos(void)
{
int mem;
int i;
double x[NVARS+1];
FILE *controlpointsarxika;
controlpointsarxika = fopen("controlpointsarxika.txt","r");
remove("save.txt");
for(mem = 0; mem < POPSIZE; mem++)
{
for(i = 0; i < NVARS; i++)
{
x[i+1] = population[mem].gene[i];
}
rbsplinearxiki();
XfoilCall();
population[mem].fitness = FileRead();
remove("save.txt");
}
fclose(controlpointsarxika);
}
For this one the compiler warns me tha variable x is set but not used...!! But actually i am using the variable x...!!!
The second function is this one...
void elitist(void)
{
int i;
double best,worst;
int best_mem,worst_mem;
best = population[0].fitness;
worst = population[0].fitness;
for(i = 0; i < POPSIZE - 1; i++)
{
if(population[i].fitness > population[i+1].fitness)
{
if(population[i].fitness >= best)
{
best = population[i].fitness;
best_mem = i;
}
if(population[i+1].fitness <= worst)
{
worst = population[i+1].fitness;
worst_mem = i+1;
}
}
else
{
if(population[i].fitness <= worst)
{
worst = population[i].fitness;
worst_mem = i;
}
if(population[i+1].fitness >= best)
{
best = population[i+1].fitness;
best_mem = i+1;
}
}
}
if(best >= population[POPSIZE].fitness)
{
for(i = 0; i < NVARS; i++)
{
population[POPSIZE].gene[i] = population[best_mem].gene[i];
}
population[POPSIZE].fitness = population[best_mem].fitness;
}
else
{
for(i = 0; i < NVARS; i++)
{
population[worst_mem].gene[i] = population[POPSIZE].gene[i];
}
population[worst_mem].fitness = population[POPSIZE].fitness;
}
}
For this one i get two warnings that the variables worst_mem and best_mem may be used uninitialized in this function..!! But i initialize values to both of them..!!
And the third function is this...
void crossover(void)
{
int mem,one;
int first = 0;
double x;
for(mem =0; mem < POPSIZE; mem++)
{
x = rand()%1000/1000;
if(x < PXOVER)
{
first++;
if(first%2 == 0)
{
random_Xover(one,mem);
}
else
{
one = mem;
}
}
}
}
For which i get that the variable one may be used unitialized..!! But it is initialized..!
Can you please tell me what is wrong with these functions...??
Thank you in advance
In your first function, you set (assign) x, but you never read it, hence you are not using it... you're only wasting CPU cycles by writing to it. (Note also that because you index it as i+1 you write beyond the space you've allocated for it).
In the second function, your initializations to those variables are in conditional blocks. You can see that (perhaps? I didn't verify) in all conditions they are initialized but your compiler isn't that smart.
In your third function, it does appear that one could be refered to without having first been initialized.
First: You set x but do not use it. It's a local variable that gets set but it's dropped as soon as the function returns.
Second: There might be values that makes it so that your best_mem/worst_mem never gets set in your if/else, but you are using them later on. If they haven't been set, they contain garbage if not initialized.
Third: While it shouldn't happen that you try to use an uninitialized variable in your code, it still looks weird and compiler doesn't see that it won't happen first time.
When you get compiler warnings, treat is as you are doing something wrong or rather not recommended and that it could be done in a better way.
The x variable is only used on the left hand side (i.e. assigned a value). You are not using that value on the right hand side or pass it to a function.
It may be possible to get to the end of the loop for(i = 0; i < POPSIZE - 1; i++) without those variables given a value. Why not set them in the declaration.
The call to random_Xover(one,mem); could be called when one is not set. Change the line int mem,one; to int mem,one = <some value>;

In C, are variables declared within a loop, local?

#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.

Resources