understanding static int execution [duplicate] - c

This question already has answers here:
unexpected output in C (recursion)
(3 answers)
Closed 7 years ago.
#include <stdio.h>
int main()
{
static int i = 5;
if(--i){
main();
printf("%d,", i);
}
return 0;
}
I'm unable to find why the value of i is becoming 0 every time.

There is a recursive call to main() in your code, till if(--i) is not down to 0. The print statement does not get a chance to execute.
Once i becomes zero, the control returns, and the value of i, is, well, 0, then.
[I don't have a photo editor handy right now, sorry],
Try to have a look at the rough graphics to get an idea.
FWIW, i is having static storage, so it holds the value across function calls.
(I assumed the last part is already understood, just adding for sake of clarity.)

here's your program's execution and values:
i = 5; --i; main ()// i==4
i = 4; --i; main ()// i==3
i = 3; --i; main ()// i==2
i = 2; --i; main ()// i==1
i = 1; --i; // i == 0 ,main is not called!
and only then the program comes back from recursion:
printf("%d,", i);

Related

why this code doesn't work ? It involves use of pointers and functions in c [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
Can someone please tell me what is wrong with this code?
#include <stdio.h>
#include <stdlib.h>
char * prime(int N);
int main()
{
char* p = prime(13);
printf("%s", p);
return 0;
}
char * prime(int N)
{
int i,j=1;
char yes[] = "Number is a prime";
char no[] = "Number is not a prime";
for(i=2; i<=N-1; i++)
{
if(N%i == 0)
j=0;
}
if(j == 1)
return yes ;
else
return no ;
}
Expected output =
Number is a prime
Shown output =
$0#
You're reading back data using a pointer which points to memory that you don't own; the behaviour on doing this is undefined.
yes and no are only defined in the function prime.
Once that function exits, the pointer is dangling.
Consider writing const char* yes = "Number is a prime"; etc. at global scope, change prime to return an int where 1 denotes primality and 0 doesn't, and use that return value in main to output the relevant string. Not only will this fix your bug but it's a nice design since prime should not really care how it's output value is consumed: that's the job of another function that's concerned with presenting the result. Your test for primality can also be optimised: in particular, you only need to go up to the square root of N.
Note how I've used const char* to indicate that the data are held in read-only memory.

C - not entering if even when he should

I'm seriously mad right now. I need to compare one string with second, when chars from second string can somehow create first string. Example
foo1 = bill
foo2 = boril
foo2 can create foo1, because it contains all the letters from foo1.
So there's my program:
secret = religion
lettersGuessed = religonvpst
for(i = 0; i < lenSecret; i++){
for(l = 0; l < lenGuessed; l++)
printf("A: %c, B: %c, C: %d\n", secret[i], lettersGuessed[l], count);
if(secret[i] == lettersGuessed[l]){
printf("HI\n");
count++;
break;
}
printf("C: %d\n", count);
}
But variable count always stays at 0. This is output from console:
http://pastebin.com/YrHiNLNi
As you can see right from beginning, when secret[i] == lettersGuessed[l] in if should return true(1), it returns false(0). What's wrong with this? Why it's not working?
It's because you don't have curly braces after your second for loop. If you don't wrap the block of code you want to iterate over with curly braces, only the code before the first semi-colon encountered will be executed. In this case, your second loop will iterate over the printf statement but nothing else. So variable l will always be equal to lenGuessed when the if statement is executed and no letter from the first word matches the last letter of the second word, therefore count is never incremented.
Ok, this is totaly crazy.
Code that I posted in my question was of course wrong, because I forget braces of second for loop. Small, but fatal mistake, I know, but I was seriously mad so I didn't pay attention. Anyway, the original code is following:
int isWordGuessed(char secret[], char lettersGuessed[]){
int i, l, count = 0;
int lenSecret = strlen(secret);
int lenGuessed = strlen(lettersGuessed);
for(i = 0; i < lenSecret; i++)
for(l = 0; l < lenGuessed; l++)
if(secret[i] == lettersGuessed[l]){
count++;
break;
}
return lenSecret == count ? 1 : 0;
}
At first, it was returning 0. After compiling it with different tools and launching it on two different OS (Windows 7 64-bit and Windows XP 32-bit) i was finaly able to get 1 from that function.
It seems like variable count had non-zero value while launching, so instead of int i, l, count; I wrote int i, l, count = 0;
Well, now I don't understand only one thing - why sometimes variables has non-zero value even when I never touched them. It happened to my before, but only in C, in other languages I never had such a problem.

rand() returns nothing but zeroes

I am trying to write a program that will assign 5 random integers to an array but so far it is filling the array with zeroes. Also, the first number can't be a zero. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
int number[5];
int main() {
int i;
int t=0;
for (int t=0;t<5;t++) {
if (i=0)
{number[i] = rand()%8+1;}
else
{number[i] = rand()%10;}
i++;
printf("%d", number[i]);
}
return (0);
}
if (i=0)
That's assignment, not equality comparison.
int i;
Also, i is uninitialized, so accessing its value is undefined behavior. Since you accidentally assigned to it instead of comparing to it, if (i=0) doesn't invoke undefined behavior, but it would if you fixed the first bug.
i++;
printf("%d", number[i]);
Incrementing i before the print means you always print the cell right after the one you were working on.
You don't actually need i; t does everything you want i to do. We'll remove i and rename t to i:
for (int i = 0; i < 5; i++) {
if (i == 0) {
number[i] = rand() % 8 + 1;
} else {
number[i] = rand() % 10;
}
printf("%d", number[i]);
}
Several things are wrong in your code ...
1)
You didn't initialize the variable i
2)
if(i=0)
should be
if( i == 0 )
3)
You can use variable t instead of i -- means variable i is unnecessary
4)
You should have a function call for randomize() function before rand() function call, so that you can get the real random numbers
5)
If you just want to show the random numbers, you don't even need to use array
You will get the same sequence of 'pseudo-random' values by calling rand() in your program. To change this sequence the Random Number generator has to be 'seeded'. This is done by calling srand() function once with a seed value at the beginning of your program.
Ideally the value used for seed should change with each run of the program. Things that you could use as the seed are the process id, time, date or any other system provided value that is guaranteed to be different for each run of the program.
void srand(unsigned int seed);
Apart from that there are logical flaws in your program as others have highlighted, of which the if conditional assignment error is the most serious.

Variable Scope in C programming

In c, when this block of code is run,it outputs 10 10 10 10 10. I think the loop should exit after 1st execution as i becomes 11 but it is not happening. Why it is so?
#include<stdio.h>
int main()
{
int i;
for(i=0;i<5;i++)
{
int i=10;
printf("%d\t",i);
i++;
}
return;
}
But when program is written as below the output is similar to what i am thinking(i.e.10 ).What is the exact difference between above code and the code shown below? How C is handling these variable? I would be glad if anyone explain about this.
#include<stdio.h>
int main()
{
int i;
for(i=0;i<5;i++)
{
i=10;
printf("%d\t",i);
i++;
}
return;
}
In your first program, for loop is using the i declared outside the for to control the loop. The printf uses the i declared inside the for loop to print the value and this i has block scope.
The new declaration of i in the for loop temporarily hides the old declaration. Now the value of i is 10. At the end of the for loop block the new i is not visible to the program and the variable regains its old meaning and this time i stores the value as per the iteration of loop (either 1, 2, 3 or 4).
In the first code you declare your variable twice: one outside the loop and the second one inside the loop. So inside the loop compiler found another declaration for the variable so it uses the inner declaration (this called block scope).
So that the first program print 10 10 10 10 10 because this is the inner declaration int i=10
But in the second code you declare it once so the compiler use this declaration in the whole program.
In C99 or later, you can write this variation on your code with 3 independent variables called i:
#include <stdio.h>
int main(void)
{
int i = 19;
printf("i0 = %d\n", i);
for (int i = 0; i < 5; i++)
{
printf("i1 = %d\n", i);
int i = 10;
printf("i2 = %d\n", i);
i++;
}
printf("i0 = %d\n", i);
return 0;
}
The output is:
i0 = 19
i1 = 0
i2 = 10
i1 = 1
i2 = 10
i1 = 2
i2 = 10
i1 = 3
i2 = 10
i1 = 4
i2 = 10
i0 = 19
(In C89, you can't have the variable tagged i1 in the output, and you couldn't demonstrate the two variables in the loop because declarations have to precede statements such as printf() calls.)
Because in first example the i inside the loop is not the same as the one which governs/controls the loop, it is a completely different variable though with same name.

Perfect Numbers bug?

Currently I have this code, and it works.
#include <stdio.h>
int isFactor(long number1, long number2)
{
int isitFactor = (number2 % number1 == 0)?1:0;
return isitFactor;
}
int isPerfect(int number)
{
int counter;
int sum;
for (counter = 1; counter < number; counter++)
if (isFactor(counter, number))
sum += counter;
return (sum == number);
}
int main()
{
int counter = 1;
for (counter = 1; counter <= 100; counter++)
{
printf("", isPerfect(counter));
if (isPerfect(counter))
printf("%d\n", counter);
}
}
However, if I take out the unnecessary line with the printf in main(), it fails to produce any numbers.... Possible causes?!
Variable sum in function isPerfect is not initialized.
You had two problems with that code, the first is that sum is not initialised and will generally be set to whatever rubbish happened to be on the stack at the time the function was called. Automatic variables are not guaranteed to be initialised to zero (or anything, for that matter) so, if you need them to start with a specific value, you have to initialise them yourself.
The second problem (now fixed with your edit) was that isFactor is missing. Although you probably want it as a function, the following code works, producing the two perfect numbers less than 100, 6 and 28:
#include "stdio.h"
#define isFactor(c,n) ((n % c) == 0)
int isPerfect (int number) {
int counter;
int sum = 0; // <-- note initialisation here.
for (counter = 1; counter < number; counter++)
if (isFactor(counter, number)) sum += counter;
return (sum == number);
}
int main (void) { // try to use one of the two canonical forms.
int counter = 1;
for (counter = 1; counter <= 100; counter++)
if (isPerfect(counter)) printf("%d\n", counter);
return 0;
}
And, looking into why it might be working with that extra printf, here's a viable explanation.
When calling a function, the local variables are allocated on the stack simply by reducing the stack pointer. Your isPerfect asembly code probably just has a prolog like:
sub %esp,8
and then you use the memory at %esp for counter and %esp + 4 for sum. Without initialising sum, it starts with whatever happened to be at that memory location, which is probably not zero.
Now think about what happens when you call printf first. It no doubt has its own local variables so it uses the part of the stack that you will later be relying on to be initialised to zero. When the printf returns, it doesn't set those memory locations back to their previous values, it just increments the stack pointer to skip over them.
Then, when you call isPerfect, there's a good chance that those memory locations will be different to what they were before you called printf, simply because printf has been using them for its own purposes.
If you're lucky (or unlucky, depending on your viewpoint), the memory location where sum will be may even be zero. But it's undefined behaviour nonetheless and you should not rely on it - initialise sum explicitly and your (immediate) problems will be over.
If this is homework, feel free to ignore this bit (in fact, actively ignore it since you may get caught out for plagiarism). This is how I would implement the isPerfect function as a first cut. It doesn't call functions to work out factors since, while they're generally quite fast, they're not without cost, and something that simple can be done in a single line of C anyway.
int isPerfect (int num) {
int i, left;
for (i = 1, left = num; i < num; i++)
if ((num % i) == 0)
left -= i;
return (left == 0);
}
There's no doubt it could be made faster but the return on investment drops away pretty quickly after a certain point.

Resources