What is the difference between two sets of code writen below - c

#include<stdio.h>
int *fun();
main()
{
int *i;
i=fun();
printf("cbgg\n");
printf("%d",*i);
getch();
}
int *fun()
{
int k;
k=5;
return (&k);
}
Though the program written above prints a garbage value for i, yet the the program written below works fine,i.e. the output is absolutely relevant, which is 5. Why is this so?
#include<stdio.h>
int inc();
main()
{
int i;
i=inc();
printf(“cbgg\n”);
printf(“%d”,i);
getch();
}
int inc()
{
int k;
k=5;
return (k);
}

The main difference is that this one does a pretty nasty thing by returning the address of a local variable (allocated on the stack) - Later usage of the returned pointer calls for undefined behavior.
int *fun()
{
int k;
k=5;
return (&k);
}
The other one is just a harmless return of 5 from the fun() routine.

To understand this you need to know a little bit about how arguments are passed to and from functions. When "fun" is called the arguments to "fun" are pushed on the stack (among other things). For "fun" to return values it pushes them on the stack and the caller later pops the value.
The local variable int k has function scope so when the function "fun" exits the stack space used is destroyed. Returning a pointer to that destroyed memory area is undefined behavior and that is what you are doing when you return &k. In #2 you instead push the value of k on the stack and that is valid.

In first case you are returning pointer to local variable,whose scope is limited to function only.
Whenever you return from function stack gets modified and you get unexpected data.

Related

Why can we initialize inside a function and still use that value outside the function?

For example:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct {
int n;
double d;
} some_thing;
void alloc_and_init_some_thing(some_thing** s, int n, double d) {
some_thing si = { .n=n, .d=d };
*s = malloc(sizeof(**s));
memcpy(*s, &si, sizeof(**s));
}
void alloc_and_init_int(int **i) {
int j = 21;
*i = malloc(sizeof(**i));
memcpy(*i, &j, sizeof(**i));
}
int main() {
some_thing *s;
alloc_and_init_some_thing(&s, 41, 31);
printf("s->n=%d s->d=%f\n", s->n, s->d);
int *i;
alloc_and_init_int(&i);
printf("*i=%d\n", *i);
return 0;
}
I'm still learning C and the difference between the stack and the heap. When we declare and initialize the variable si in the function alloc_and_init_some_thing, doesn't this value exist on the stack? Hence it should get wiped out when the function finishes?
But I can see that that doesn't actually occur. Back in the main function, when we print s->n, we get the value 41.
Similarly, when we print the value for *i in the main function, it prints 21.
Why is that?
The line memcpy(*s, &si, sizeof(**s)); copies the the structure si on the stack into the heap allocated structure s, thus making it persist in memory as heap allocations can be accessed anywhere in the program. It's merely a pointer to an address in memory.
The same thing happens in the similar function.
You are right that the lifetime of "si" and "j" are limited to their respective functions and not available after the return from those functions. However, their contents have been replicated via malloc/memcpy prior to the return of the functions and the pointers to the replicas are stored in variables "s" and "i", which are still alive at the time of printing (or using) those replicas.

Is it possible for a variable in a function to hold an old value from old calls of the function in C?

I'm having something like this:
void test(int iter){
int i;
if(iter>3){
i=5;
printf("%d",i);
}else{
printf("%d",i);
}
return;
}
int main(){
test(5);
test(2);
return 1;
}
This is just for example. Is it possible when called by main variable i hold value of 5 (in memory) if at least iter is greater than 3?
I know that it is not normal. But I have a function in my program (I don't have static var that is doing this) which does it. So maybe the address where this variable is initialised each time the same (so I'm getting the old value)? Or what does happen? I don't want to hold the old value or something. I'm just curious: how is this possible?
If i is stored at some location on the stack, and if that location is not modified, then i will retain it's value.
Assuming that i is even stored on the stack (optimization may eliminate this), if there is an interrupt that uses the stack (or perhaps a context switch due to time slice), the stack area below the stack pointer will get overwritten. Some compilers may fill in the stack area, usually in debug mode. Visual Studio in debug mode will catch the usage of an uninitialized variable with the above code.
In this example you are showing us, you never initialize i with a value, and it is never assigned a value unless iter is > 3.
Its value is undefined until you actually set it to something, which you only do in the "if" part of your "if then else" clause.
So it's perfectly normal that you might have a garbage value in i when iter is 3 or less.
Declear your variable Global (out of function).
for example:
int a=0;
void f(){
a++;
}
this way the value will not be lost after execution of function.
Do this:
void test(int iter){
static int i;
if(iter>3){
i=5;
printf("%d",i);
}else{
printf("%d",i);
}
return;
}
int main(){
test(5);
test(2);
return 1;
}
Note the static keyword in the static int i; line.

Use of automatic variable outside its scope in C [duplicate]

This question already has answers here:
What happens when a variable goes out of scope?
(3 answers)
Closed 6 years ago.
I am studying the working of an automatic variable. I know that it is only accessible inside the block or function in which it is declared and its lifetime is within that same function or block. So the following piece of code I am trying to check.
/Declaration of header files/
void testfn(void);
int *p;
int main(void)
{
testfn();
print("%d\n",*p);
return 0;
}
void testfn(void)
{
int x=444;
p=&x;
}
The output is - 444
I am wondering that when the testfn(); exits,the variable x will be destroyed. Then how in main function the pointer (*p) prints 444.
How this works...or if I am missing something.
Please clarify my doubt.
Thanks
It is coincidence that the original value still remains. With another compiler, or with another compilation configuration, it could take any other value or the program could just crash.
If between the testfn and printf functions you call any other function that does something with its local variables, you might see that the 444 value is not obtained anymore. But this is just, again, coincidence.
p points to the stack where x was stored. If the memory location hasn't been used for something else you will most likely get 444.
Try to insert another function call before printing p and see what happens:
#include <stdio.h>
#include <math.h>
void foo() {
int y=123;
}
void testfn(void);
int *p;
int main(void)
{
testfn();
foo();
printf("%d\n",*p);
return 0;
}
void testfn(void)
{
int x=444;
p=&x;
}
On my machine, the output is now:
123
Since the code results in undefined behaviour, the result could be different if I try this on another platform. But you can see that undefined behaviour can lead to strange bugs.
The memory location that was previously reserved for variable x is not overwritten yet. But it may be at any time. That's why your code leads to undefined behaviour.
In the following example, the memory location that was previously reserved for variable x will be overwritten by the value that is assigned to the variable y. Since the pointer p still points to that location, *p will evaluate to this new value:
#include <stdio.h>
int *p;
void test1(void) {
int x = 444;
p = &x;
}
void test2() {
int y = 15;
}
int main(void) {
test1();
test2();
printf("%d\n",*p);
return 0;
}
The fact that the value still remains is completly coincidental (not guaranteed) because nothing has overwritten it yet.
You can not count on this, it may fail, may print garbage or may crash your program or pc even.
Don't use this, it is considered undefined behavior.

Why uninitialized local variable always has the same initial value?

In this piece of code, why in my testing the result is always 1, 2, and 3?
#include <stdio.h>
void test() {
int a;
a++;
printf("%d",a);
}
int main(int argc, char *argv[]) {
test();
test();
test();
}
I think the variable in test() is static, isn't it? And Why?
The variable is not static. You're accessing an uninitialized variable. The behavior is undefined.
As other answers told, your variable is not initialized.
It prints 1, 2 and 3 possibly because of your compiler compiled the code with prolog(prologue) that cleans the stack with zeros.
The local variables in C, actually point to the offset on your stack, and the stack frame will be restored after the call is returned.
I googled and selected a artical randomly that told about this, see [How function calls work?].
Here is a video talk about that [Assembly Programming Assembly Function Stack Frame Explained ] (again, selected randomly).
And Wikipedia explains the [Call stack] as well.
Because you are working with an unintialize value... (random behaviour in this case).
Initialize your variable (example to 0) :
#include <stdio.h>
void test(){
int a=0;
a++;
printf("%d",a);
}
int main(int argc, char *argv[]) {
test();
test();
test();
}
No, your variable is not static at all!
https://stackoverflow.com/a/1597426/1758762
Static variables (file scope and function static) are initialized to zero:
int x; // zero
int y = 0; // also zero
void foo() {
static int x; // also zero
}
Non-static variables (local variables) are indeterminate. Reading them prior to assigning a value results in undefined behavior.
void foo() {
int x;
printf("%d", x); // the compiler is free to crash here
}
the variable you are trying to print is not static and neither it is initialized , thus it is taking garbage value , which seems random to you , if you execute this program on a different machine ,then there you will have different output because there you will have different garbage value
in order to avoid it , you will have to initialize your variable with some value

simple pointers to pointers

I know why this works:
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
*number = p;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
What I don't understand is why this doesn't (in my machine it prints 3700 or something like that).
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
int **x = &p;
number = x;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
Why aren't both equivalent?
both are evil as they capture the address of a stack variable.
Second one doesn't do what you expect because you are assigning directly to the parameter number, which is only temporary, the first one changes something the parameter number pointers to, which is the same thing as number in main points to.
I assume they're not equivalent because number is passed by value, on the stack, as is standard for function parameters. Any changes that you make directly to number inside of cool_number() are modifying the local copy on the stack, and are not reflected in the value of number in main().
You get around this in the first example by dereferencing number, which tells the computer to modify some specific location in memory that you also happen to have a pointer to back in main(). You don't have this in the second example, so all that happens is that you make the local number pointer point to somewhere else, without actually updating any memory location being referred to back in main(). Thus nothing you do shows up once you get back to main().
And since value is local to the cool_number() function, setting a reference to it that will be accessed after cool_number() returns isn't guaranteed to work and certainly shouldn't be used in any code outside of a trivial/toy example. But in this specific instance it's not really related to why you're seeing different results between the two pieces of code.
As I understand, in both cases, your code is wrong.
In the first case, you are returning an address to a variable allocated on stack, which will be deallocated as soon as the function returns.
In the second case, the error of the first case exists, plus you are passing number by value, so an updation to number will not get reflected in the caller function.
In 'C', arguments are always passed by value. So, you cannot update the argument passed as it is. For Ex:
int func(int a)
{
a = 5; // In this case the value 5 will not be reflected in the caller as what is updated is the local copy of a on the stack
}
int func(int *a)
{
*a = 5; // This update will show in caller as you are directly updating the memory pointed to by a
a = malloc(4); //This update will not show in caller as again you are updating the local copy of stack
}
#include <stdio.h>
void cool_number(int **number) {
int value = 42; /* this "value" hold 42 value,
and it lifetime is only in this function */
int *p = &value; /* here we get the address of "value" in memory */
*number = p;
}
int main () {
int *number;
cool_number(&number); /* after this function the "value" in memory had been recyled
and may be used by other program */
printf("number is %d\n", *number); /* so when we print value here it will be
a unpredictable value, somehow may be crash */
return 0;
}
both the same principle

Resources