Checking pointer address and value from a function - c

I'm a beginner to C and have been reading a book called "Understanding and Using C Pointers" and ended up running into a problem with using the printf function.
When using debug_p, it turns out that the address of the pointer num_p is different but exact to num in debug, but it returns the correct value when attempting a printf within main().
My question is, why is this so? Is there an appropriate way to do a printf within a function and have a correct address of a pointer?
#include <stdio.h>
void debug(int num)
{
printf("Address of num: %i Value: %i\n", &num, num);
}
void debug_p(int *num_p)
{
printf("Address of num_p: %i Value %i\n", &num_p, num_p);
}
int main()
{
int num=11;
int *num_p=&num;
printf("Address of num: %i Value: %i\n", &num, num);
printf("Address of num_p: %i Value: %i\n\n", &num_p, num_p);
debug(num);
debug_p(num_p);
return 0;
}
Output from main():
Address of num: 2358860 Value: 11
Address of num_p: 2358848 Value: 2358860
Output from debug, then debug_p:
Address of num: 2358816 Value: 11
Address of num_p: 2358816 Value 2358860

When you pass a variable to a function, you only pass the value of this variable. You never pass the address, because a new variable is created in that function. The parameters that you see in the signature of the function are all local variables, just like you would write them in the function body. These parameters are filled with the value that you pass when you call the function - but again, you are just passing the value to new variables.
void function(int a) { printf(a); }
int a = 5;
function(a);
In this example, there exist two distinct variables which have completely different addresses. They just have the same value (which is 5), but their addresses are very different.
The same happens in your debug function: num in there is not the same variable as num in main, they just have the same value (because you "gave" the value of num in main to num in debug), but not the same address. Now since num_p in debug_p still points to num in main and not to num in debug, the addresses are different.

The reason why num and num_p have the same address in both functions is because of how the stack works: The first call to debug allocates a variable on the stack. Then, when the function returns, the stack is freed again. Now you call debug_p, and therefore another variable is allocated. It will use the same place in memory as before, because the stack is built up in the same way.

Related

How can I tell when a function is accessing a local or external variable?

I am currently attempting to understand this code I came across a C certification test. The correct output of the code is 12, 13, 13.
I tried printing out the values, before it calls the 3 final outputs and i noticed the reason being is that there's a scope difference between the external x declared at the top and the one inside the function. My question is, how do I know which of those functions are accessing which object throughout the code?
#include <stdio.h>
#include <stdlib.h>
int x;
int modifyvalue()
{
return(x+=10);
}
int changevalue(int x)
{
return(x+=1);
}
int main(){
int x=10;
x++;
printf("[1] %d \n\n", x);
changevalue(x);
printf("[2] %d \n\n", x);
x++;
printf("[3] %d \n\n", x);
modifyvalue();
printf("First output:%d \n\n\n",x);
x++;
changevalue(x);
printf("Second output:%d \n\n\n",x);
modifyvalue();
printf("Third output:%dn \n\n\n",x);
}
Always take the variable from nearest scope.
Whenever the printf("...", x) is called, it takes the x from the function main().
The function modifyvalue() always operates on the x outside of all functions.
The function changevalue(int x) always operates on the parameter x - which is a copy of the variable passed in.
So in your case, both functions essentially do nothing to the x in main().
The rule is simple, in every { ... } (block) you can reference either a variable that is define in that block or any "parent" of it. For example in your code:
modifyvalue: no x, x is in parent, "global"
changevalue: x is a parameter, increment the parameter, change not reflected on the caller (because the parameter is a copy)
main: x is local
Notice that you are printing always "the main's x" that is incremented only in the main.
As noted by #Jens, the parent scope in C is called enclosing block and the global scope is called program scope (file scope + external)

Inconsistent array values when initialized from fscanf() in C

If a multi-dimensional array in main() gets initialized from a functions pointer like this:
#include <stdio.h>
void arrayfunction(int (*n)[3][3])
{
(*n)[0][2]=7;
printf("Function output: %i\n", *n[0][2]);
}
main()
{
int y[3][3];
arrayfunction(&y);
printf("Main output: %i \n",y[0][2]);
return(0);
}
then array in main() will hold the correct value, but the output from the pointer in arrayfunction() will not:
Function output: 4195805
Main output: 7
However, if the function initializes the array in main() through the functions pointer via fscanf():
#include <stdio.h>
void readSchedule(int (*s)[3][3]){
FILE *schedule;
schedule=fopen("/var/schedule.conf","r");
fscanf(schedule,"[%i,%i,%i,%i]\n",s[0][0], s[0][1], s[0][2], s[0][3]);
fclose(schedule);
printf("Function output value: %i\n",*s[0][2]);
}
main()
{
int x[3][3];
readSchedule(&x);
printf("Main output value: %i\n ",x[0][2]);
return(0);
}
Then the values are reversed, the pointer local to the function will output the correct value, but the array it points to in main() will not:
Function output value: 7
Main output value: 0
Why do the correct values only show up in the array local to main() in the first example, but only show up in the pointer local to the function in the second example?
Check the operator precedence and notice the difference in the two lines using n in arrayFunction
(*n)[0][2]=7;
printf("Function output: %i\n", *n[0][2]);
The parenthesis are critical here. The [] operator has a higher precedence than * (http://en.cppreference.com/w/cpp/language/operator_precedence). If you add parenthesis in the printf line you'll see what you expect.
More or less the same thing is going on in with the fscanf example. The compiler is treating s[0][0] as a pointer to an int (like this *(s[0][0])) so the data is getting written to an undefined area.
If you use a memory debugging program like valgrind you'll see tons of errors.
The problem in the first example is solved in the syntax of the pointer to array argument in the printf statement inside the function by changing the precedence from:
printf("Function output: %i\n", *n[0][2]);
to
printf("Function output: %i\n", (*n)[0][2]);
In the second example, fscanf() was apparently stuffing values directly into *s[][] instead of indirectly initializing the array in main() that *s[][] points to. So instead of this:
fscanf(schedule,"[%i,%i,%i,%i]\n",s[0][0], s[0][1], s[0][2], s[0][3]);
the syntax needs to be this:
fscanf(schedule,"[%i,%i,%i,%i]\n",&(*s)[0][0], &(*s)[0][1], &(*s)[0][2], &(*s)[0][3]);
in order to reach through *s[][] and place the values in y[][].

Difference in address of variable when printing in main and in a function

#include <stdio.h>
void printaddr(int n)
{
printf("%p", &n);
}
int main()
{
int n;
scanf("%d",&n);
printf("%p \n", &n);
printaddr(n);
}
Address of variable n in main loop is printed : 0028FF0C , while in function printaddr its printed 0028FEF0 .
I want to know why is there difference in address and whether or not does that difference represent anything ?
The addresses are different because they are two different variables.
When you call a function, the function parameters are initialized with copies of the function argument values. If you changed n inside printaddr, it would have no effect on the value of n inside main.
The function gets a copy of the variable, because of pass-by-value semantics. So, it's actually a different variable. The addresses are different because the memory is different.
As a test, try changing n in printaddr and seeing if it changes in main. Hint, it won't.
You can pass a pointer to a function if you want to have access to the same chunk of memory.
To expand on what Arun A.S has mentioned:
You are calling the function:
void printaddr(int n)
and you caller is passing in n (by value) rather than &n (the address of n), so you are passing by value rather than reference.
When you pass by value the value is locally copied to the function, so the original value is not changed.
Once the function completes, the local copy of n is destroyed unless you return the value.
This is why if you change the value of n in that same function (without returning the value) it will not be the same value when you access the variable n from your main.
Because in
void printaddr(int n)
you are creating a new local variable n ( local to the function ) with a different address.
You could instead use a pointer like
void printaddr(int *n)
and call it as
printaddr(&n);
So, if you change your code to
#include<stdio.h>
void printaddr(int *n)
{
printf("%p", n);
}
int main()
{
int n;
scanf("%d",&n);
printf("%p \n", &n);
printaddr(&n);
}
You will get the same address. ( But please note that the n inside the function would just point to the address of the n from main() , it does not have the same address as it )

How do you pass the result from one function into another function?

Please consider this code example:
int func1(int,int); // function 1 prototype
int func2(int); // function 2 prototype
I am trying to send the output of function-1 as the input to function-2, but have been unsuccessful till now.
If someone could please explain the same with an example, that would be great.
Also, is the same possible with respect to Pass-by value and Pass-by-reference?
How about simply
int x = func2(func1(1,2));
int a = func2(func1(7, 9));
Just pass the expression containing the call to func1 as the argument to func2.
You could do this by nesting functions:
func2( func1(42, 24) );
Nesting lots of functions can easily become hard to read, so for more readability you could store the return value of func1 in a temporary variable:
int tmp = func1(42, 24);
func2(tmp);
Regarding your question about pass-by-reference vs. pass-by-value: In all these function calls, the parameters are passed by value. That's because the function signatures define the parameters as int, not int *
As the other answers said: func2( func1(1, 2) );
In C you can only pass parameters by value. Now having said that, passing the value of a pointer that points to the memory you want to change achieves the same effect as passing by reference.
int foo(int *x){
printf("The address that you passed to the function is: %x", x);
printf("The value is: %d", *x);
*x = 10;
}
int mem;
foo(&mem); //print the address of mem
in C++, you can pass by refference.
int foo(int &x){
printf("The address that you passed to the function is: %x", &x);
printf("The value is: %d", x);
x = 10;
}
int mem;
foo(mem); //print the address of mem

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