C - Pass By Value and Pass By Reference Inconsistency - c

When using pass by reference in C, sometimes the address passed to the called function changes:
void mainFunction()
{
BYTE aAddress[10];
readFunction(aAddress); // Address of aAddress: 0x111111
}
void readFunction(BYTE *pAddress) // Address of pAddress: 0x222222
{
...
}
Another issue I encountered, when using pass by value, the value received by the called function differs from what is passed to it.
void mainFunction()
{
readFunction(0x20); // Passed value: 0x20
}
void readFunction(BYTE uValue) // Received value: 0x00
{
...
}

It all depends: How did you print the addresses? If you get the address of the variable, then of course they will be different. The value the pointers point to, however, will be the same::
int main ( void )
{
char some_array[100];
printf("array holds: %p\n", (void*) some_array);//same
printf("Address in main: %p\n", (void*) &some_array[0]);//same
pass_arr(some_array);
return 0;
}
void pass_arr(char *arr)
{
printf("Address of pointer VAR: %p\n", (void *) &arr);//PRINTS DIFFERENT ADDRESS
printf("Pointer address: %p\n", (void *) arr);//same
printf("points to: %p\n", (void *) &(*arr));//same
}
check this codepad
You probably failed to print the address of a variable correctly, the only right way is to use the %p placeholder, and to cast the address to void *. This is down to the fact that the way addresses are printed out is implementation dependent.
That said, you mention "pass by reference". C doesn't pass by reference, it doesn't have references in the C++ sense. But in order for a function to alter the value of something else, you ought to pass a pointer to a pointer:
struct some_str
{
int mem1;
size_t mem2;
};
int main ( void )
{
struct some_str *foo = malloc(sizeof *foo);
set_value(&foo);
free(foo);
return 0;
}
void set_value(struct some_str **change)
{//pointer to pointer
static int change_count = 0;
(*change)->mem1 = 123;
(*change)->mem2 = ++change_count;//for example
}
C always passes by value, in case of a pointer, that value is a memory address, in case of a primitive type (int, char, long...), it's not the variable but the value you're passing, if you pass a pointer to the variable (&my_int), you're not passing the variable, but its address in memory. Those are the only 2 options you have to choose from.
For more on the subject (arrays vs pointers, and why arrays decay into pointers in most cases you may find this link useful)

When using pass by reference in C, sometimes the address passed to the called function changes
--> NO. Look at this code
#include <stdio.h>
void readFunction (int *pAddress)
{
printf("Address of pAddress: %p\n", &pAddress);
printf("Content of pAddress: %p\n", pAddress);
}
void main()
{
int a[10];
printf("Address of a: %p\n", &a);
readFunction(a);
}
when execute it, you will get something as:
Address of a: 0xbfb94948
Address of pAddress: 0xbfb94930
Content of pAddress: 0xbfb94948
The pAddress is located in another place but it still points to the address of a. And this is the primitive of pass by reference

Related

Can anyone explain why the address of a pointer change when called by another function? How to make nPtr=Ptr?

I noticed that my pointer address is different when it is passed to a function. U am not sure to access the value that exists inside the function? Please don't suggest returning the pointer value from the function. I strictly want to use void function.
output:
&nPtr = 6422300
&Ptr = 6422272
&nPtr = 6422300
See the below code:
#include<stdio.h>
void myFunc(int *Ptr){
printf("&Ptr = %d\n", &Ptr);
};
void main(){
int *nPtr;
printf("&nPtr = %d\n", &nPtr);
myFunc(nPtr);
printf("&nPtr = %d\n", &nPtr);
}
Let me be more clear. Here is the code that I am trying to fix. All what I want is to make the two pointers point to the same address. I want to use the best coding practice.
#include<stdlib.h>
#include<stdio.h>
void myFunc(int *Ptr){
Ptr = malloc(10*sizeof(int));
printf("*Ptr = %d\n", *Ptr);
};
void main(){
int *nPtr;
printf("*nPtr = %d\n", *nPtr);
myFunc(nPtr);
printf("*nPtr = %d\n", *nPtr);
}
In main(), you're getting the address of nPtr in main()'s stack frame; in myFunc(), you're getting the address of the copy of nPtr that is being passed by value to myFunc() as Ptr (so you're actually getting the address of Ptr, which is distinct) and exists on myFunc()'s stack frame.
nPtr and Ptr are separate variables in separate functions, and as such each must necessarily have a different address, i.e. &nPtr == &Ptr will always be false.
But you asked about nPtr == Ptr, i.e. can they contain the same value, and as pointers they can both contain the same pointer value. For example:
#include<stdio.h>
void myFunc(int *Ptr){
printf("Ptr = %p\n", (void *)Ptr);
};
int main(){
int x;
int *nPtr = &x;
printf("nPtr = %p\n", (void *)nPtr);
myFunc(nPtr);
printf("nPtr = %p\n", (void *)nPtr);
}
Output:
nPtr = 0x7ffe9a615104
Ptr = 0x7ffe9a615104
nPtr = 0x7ffe9a615104
For this function
void myFunc(int *Ptr){
printf("&Ptr = %d\n", &Ptr);
};
when you call it, although you are passing a pointer (which is for pointing to an integer) to this function , the system is creating a copy of the pointer and of course they will be at different memory address.
Hence when you return back to the main and retrieve your original pointer address, it will be displaying back the original address

Passing pointer to function is'nt passing by reference in C?

#include<stdio.h>
int func(int*);
int main(void)
{
int a = 3;
int *p = NULL;
p = &a;
printf("p = %p\n", p);
func(p);
printf("p inc: %p\n", p);
return 0;
}
int func(int *p)
{
p++;
return 0;
}
Output: p=0x7fff6f87e89c
p inc:0x7fff6f87e89c
Pointer p is passed to function func and pointer p is incremented in func, but in main function its address is still the same!! Passing pointer to function is'nt passing by reference?
Pointers are passed by value.
If you want to pass a pointer by reference, you just pass a pointer of a pointer!
Like so:
#include<stdio.h>
int func(int**);
int main(void)
{
int a = 3;
int *p = NULL;
p = &a;
printf("p = %p\n", p);
func(&p);
printf("p inc: %p\n", p);
return 0;
}
int func(int **p)
{
(*p)++;
return 0;
}
There's no passing by reference in C. When you pass a pointer to a function, you are passing a memory address by value.
When, inside the function, you do this:
int func(int *p)
{
p++;
return 0;
}
...you are only incrementing the memory address indicated by the parameter p by sizeof *p bytes.
In order to "simulate" passage by reference in C, you need to explicitly dereference the pointer to access the actual object. If p is a properly assigned and valid pointer, then *p is the object it points to. If a non-pointer expression were this:
a = a + 1;
...then with p == &a it would become this:
*p = *p + 1;
...or simply (*p)++. Notice that the parenthesis are necessary because, otherwise, C will read this as *(p++). You can also get used to writing ++*p instead.
You increment the pointer, not the value.
Try like this
(*p)++;
And
printf("p inc: %d\n", *p);
You need to understand pointers. A pointer is simply a variable that stores the memory address where the data actually is. You can access the data by using the dereference operator *, so if you want to change the data, you simply dereference the pointer, and then modify the data.
Likewise, for printing you want to see the value of the data.
In your code, you only modify the pointer. In c you always pass by value, a copy of the pointer itself is created inside the func() function, initially it holds the same address as your original pointer, but since it's a copy, increment it will only affect the address in the local copy.
Further more, since it's pointing to a variable on the stack. The increment operation on it will result in a pointer that you can't dereference because it would be undefined behavior.
If you want to increment the address of the pointer, you need to pass a pointer to the pointer, like this
void func(int **p)
{
(*p)++;
}
and in main
func(&p);
note that the body of func() is the same, because you once again need to get access to the memory pointed to by p in order to modify it.

Why can't I pass a pointer as an argument?

I am attempting to retrieve a pointer via a function in c. If the pointer is a return value from the function then it works. But if I pass the address of the pointer to the function, I can't update the dereferenced pointer value (which should be the address stored in the pointer) from within the function.
Please see the code and the output. Why don't I get the same results with both GetPointer1() and GetPointer2()? What am I missing?
#include <stdio.h>
#include <stdint.h>
uint8_t SrcArray[2][3] = {{11,12,13},{21,22,23}};
uint8_t *p1;
uint8_t *p2;
void GetPointer1(uint8_t *p);
uint8_t* GetPointer2(void);
int main()
{
printf ("&SrcArray[0][0]: %d\n", &SrcArray[0][0]);
GetPointer1(p1);
p2 = GetPointer2();
printf ("p1: %d\n",p1);
printf ("p2: %d\n",p2);
return 0;
}
void GetPointer1(uint8_t *p)
{
p = &SrcArray[0][0];
}
uint8_t* GetPointer2(void)
{
return &SrcArray[0][0];
}
Output:
&SrcArray[0][0]: 6295604
p1: 0
p2: 6295604
That is because the pointer you have in the function signature of GetPointer1(uint8_t *p) is passed by value. If you want to modify the pointer itself, you have to pass a pointer to a pointer:
void GetPointer1(uint8_t **p) {
*p = &SrcArray[0][0];
}
Otherwise, you may modify the piece memory to which the pointer points, but not the pointer itself.
Its is local to function GetPointer1 because it is a local variable which is passed as an value not as an address.
Here is the output details of your code for better understanding
inside main: &SrcArray[0][0]: 6295616
value of pointer p1: 0
address of pointer p1: 6295640
inside GetPointer1: 0
value of pointer p: 0 //which ur taking to a pointer p and modifying p whihc is local to that function.
address of pointer p: 64030024
inside GetPointer1 after assignment:value of pointer p: 6295616
address of pointer p: 64030024
If you want to pass address you need to use & before the variable say &p1.
Also as mentioned in one of the answer by IGarFieldI you can use pointer to a pointer.
void GetPointer1(uint8_t **p) {
*p = &SrcArray[0][0];
}
One more point since P1 is global variable, its accessible to all the functions you can directly use P1=SrcArray; which is allowed and does the same task.
ScrArray is equivalent &ScrArray[][] both gives the address of the array.
You have a variable p1 that is pointing to something. Then you pass it to a function GetPointer1. What happens there is that the value of the variable p1 (this is the address of the value it is pointing to!!!) is copied (!) to the function stack. This means that you can modify the pointed value (*p1), but not the original pointer (p1) itself, as you only have a copy of it. If you want to be able to modify the original pointer, then you have to retrieve the address of the pointer and pass this one to the function, i. e. you need a pointer to the pointer. You get this via the address-of operator &. So you need this:
getPointer1(uint8_t** p) { *p = /*...*/; }
and call it via
getPointer1(&p1);
#include <stdio.h>
#include <stdint.h>
int SrcArray[2][3] = {{11,12,13},{21,22,23}};
int *p1;
int *p2;
void GetPointer1(int **p);
int* GetPointer2(void);
int main()
{
printf ("&SrcArray[0][0]: %d\n", SrcArray[0][0]);
GetPointer1(&p1); /*<-- passing the reference of pointer p1 */
p2 = GetPointer2();
printf ("p1: %d\n",*p1);
printf ("p2: %d\n",*p2);
return 0;
}
void GetPointer1(int **p) /*<-- using double pointer */
{
*p = &SrcArray[0][0];
}
int* GetPointer2(void)
{
return &SrcArray[0][0];
}
o/p
rabi#rabi-VirtualBox:~/rabi/c$ gcc -g stack3.c
rabi#rabi-VirtualBox:~/rabi/c$ ./a.out
&SrcArray[0][0]: 11
p1: 11
p2: 11
rabi#rabi-VirtualBox:~/rabi/c$
" But if I pass the address of the pointer to the function." But you're not passing the address of the pointer, you're passing a copy of the pointer; changing the copy (as you noticed), doesn't change the original. If you actually pass in the &p (address of p) like you intended, you will be able to modify it - I'm unsure of syntax. edit: void GetPointer1(uint8_t **p) maybe?

If p is a pointer to int where would one use &p

In the following code p is pointer to an int. It is quite clear that p points to the address of i. Through my research i know &p points to the address of pointer p. But i don't get why would you need separate address for that. And also when would you use &p.
int main() {
int i = 3, *p = &i;
printf("%p",&p);
printf("%p",p);
return 0;
}
If p is pointer to int then
int **q = &p;
When you want to use pointer to pointer, then use the address of a single pointer to assign it to pointer to pointer.
Just to make a point that pointer is also a data-type and it stored in the memory location and it holds a valid memory location as its value. The address in which this valid memory location is stored is given by &p
Your printf() also needs to be fixed. %p expects void *
printf("%p",(void *)p);
But i don't get why would you need separate address for that
You don't, but there exists the address of operator so you can take the address of a pointer, which is what
printf("%p\n", &p);
is printing.
And also when would you use &p
There are cases where this might be useful, consider for example that you need to pass a pointer to a function which could be reassigned into the function, you can do something like this
int allocateIntegerArray(int **pointerToPointer, size_t someSize)
{
if (pointerToPointer == NULL)
return 0;
*pointerToPointer = malloc(someSize * sizeof(int));
return (*pointerToPointer != NULL);
}
then you could use this funciton the following way
int *pointer;
if (allocateIntergerArray(&pointer, 10) == 0)
{
fprintf(stderr, "Error, cannot allocate integer array\n");
/* do some extra cleanup or recover from this error, or exit() */
exit(0);
}
The pointers themselves are also variables and as such they need to be sotred somewhere, so the address of a pointer tells you where is the pointer stored, it's value tells you where it is pointing to.
By knowing where it is stored you can do things like the one explained above.
A trivial example:
int nochange(int *c, int *val)
{
c = val; // Changes local pointer c to point to val
// Note that C passes copies of the arguments, not actual references.
}
int do_change(int **c, int *val)
{
*c = val; // Accesses the real pointer c at its real location and makes
// that one point to val
// Even though c is a pointer-to-pointer copy, its value is
// copied too, and the value is the address of the real c
}
int main()
{
int a = 1;
int b = 2;
int *c = &a; // A pointer is also a datatype that resides in memory
printf("%d\n", *c); // Will print 1
nochange(c, &b);
printf("%d\n", *c); // Will print 1
do_change(&c, &b);
printf("%d\n", *c); // Will print 2 because c now points to b
}
I have a similar answer with a bit more detail here about pointer vs pointer-to-pointer: pointer of a pointer in linked list append

void pointer as argument [duplicate]

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 3 years ago.
The following C snippet:
[...]
void f1(void* a){
printf("f(a) address = %p \n",a);
a = (void*)(int*)malloc(sizeof(int));
printf("a address = %p \n",a);
*(int*)a = 3;
printf("data = %d\n",*(int*)a);
}
void f(void){
void* a1=NULL;
printf("a1 address = %p \n",a1);
f1(a1);
printf("a1 address = %p \n",a1);
printf("Data.a1 = %d\n",*(int*)a1);
}
[...]
results in
a1 address = (nil)
f(a) address = (nil)
a address = 0xb3f010
data = 3
a1 address = (nil)
Segmentation fault (core dumped)
Why doesn't a1 keep the address that has been assigned to it in the function?
As this is C, you cannot pass the pointer by reference without passing in a pointer to the pointer (e.g., void ** rather than void * to point to the pointer). You need to return the new pointer. What is happening:
f(a1);
Pushes the value of the pointer (NULL) as the stack parameter value for a. a picks up this value, and then reassigns itself a new value (the malloced address). As it was passed by value, nothing changes for a1.
If this were C++, you could achieve what you want by passing the pointer by reference:
void f(void *&a);
Passing a pointer to a1 to your function, you can't change where a1 points. The pointer is passed by value, so in f1 you're only changing a copy of the address held by a. If you want to change the pointer, i.e. allocate new memory for the pointer passed in, then you'll need to pass a pointer to a pointer:
void f1(void **a)
{
// ...
*a = malloc(sizeof(int));
// ...
To change a variable via a function call, the function needs to have reference semantics with respect to the argument. C doesn't have native reference variables, but can implement reference semantics by means of taking addresses and passing pointers.
Generally:
void mutate_thing(Thing * x) // callee accepts pointer
{
*x = stuff; // callee derefences ("*")
}
int main()
{
Thing y;
mutate_thing(&y); // caller takes address-of ("&")
}
In your case, the Thing is void *:
void f(void ** pv)
{
*pv = malloc(12); // or whatever
}
int main()
{
void * a1;
f(&a1);
}
Based on Kerrek SB's example I came with this to demonstrate void pointer-to-pointer as an argument and how it may be used.
#include <stdio.h>
void test(void ** jeez)
{
*jeez = (void *) (int) 3;
}
int main (int argc, char* argv[])
{
void *a;
test(&a);
int b = *(int *)&a;
printf("value returned = %d\n", b);
return 0;
}

Resources