Reputation: 1064
I was trying to pass a character array 'p' to a function 'func' and getting it copied to another argument 'arg' inside the function. But, the array is not getting copied, though I'm able to modify the content of 'p' in the 'func' and able to verify the changes in the main function, the 'res' doesn't get copied with the values from 'p'. It prints blank. I'm not sure what mistake I'm making.
#include <stdio.h>
#include <stdlib.h>
void func(char *c, int size, char *res)
{
int i;
printf("Printing c in func...\n");
for(i=0;i<size;i++) {
printf("%c",c[i]);
}
printf("\n");
c[2] = 'j';
res = c;
}
int main(void)
{
char c[5]={'h','e','l','l','o'};
char *p,*arg;
int i, size = 5;
p=c;
arg = (char*)malloc(size);
func(p,size,arg);
printf("Printing p in main...\n");
for(i=0;i<size;i++) {
printf("%c",p[i]);
}
printf("\n");
printf("Printing arg in main...\n");
for(i=0;i<size;i++) {
printf("%c",arg[i]);
}
printf("\n");
return 0;
}
Output:
Printing c in func...
hello
Printing p in main...
hejlo
Printing arg in main...
Upvotes: 1
Views: 55
Reputation: 106102
In C, arguments to a function are passed by value. The location res
and c
does not exists after function execution reaches its end. Note that the changes you are doing is with the pointers itself and not the location pointer points to. So any changes to res
will not be visible to main
.
To make the changes visible to main
you need to pass address of arg
to function func
.
func
signature should be
void func(char *c, int size, char **res) ;
and its call from main
should be
func(p, size, &arg);
Also change the assignment res = c;
to *res = c;
in function func
.
In this case you are passing the address of pointer arg
and changes are done to the location res
is pointing to. res
is pointing to the address of reg
so any changes to the address pointed by res
will be persist and visible to main
.
Now see how it works. Initially when you call your function func
after the suggested changes:
+-----------+ (0x300 is a random memory location)
| |
arg | 0x300 | <---------+
| | |
+-----------+ |
0x100 |
|
|
+-----------+ |
| | |
res | 0x100 +-----------+
| |
+-----------+
0x200
When you assign c
to *res
(an alias of reg
), *res
will make reg
to point to where c
points to. Assuming string hello
is stored at 0x500
then *res = c
will make reg
to point to 0x500
:
Array c (in main)
+-----------+ +-----+-----+-----+-----+-----+------+
| +--------------------------------->+ 'h' | 'e' | 'j' | 'l' | 'o' | '\0' |
arg | 0x500 | <---------+ +-----+-----+-----+-----+-----+-------
| | | 0x500 ....
+-----------+ |
0x100 |
| *res = c
|
+-----------+ |
| | |
res | 0x100 +-----------+
| |
+-----------+
0x200
Upvotes: 2
Reputation: 29744
In C pointers ar epassed by value to functions, so in your function:
void func(char *c, int size, char *res)
res is a totally different object than pointer passed to it
func(p, size, arg);
that is it is different than arg
, but it points (only points) to the same location as arg
pointed at the time it was passed to this function.
Therefore assignment
res = c;
mad inside that function changes only local pointer (the one inside the function). If you instead did
*res = *c;
then the memory pointed to would be changed and that would be visible from the outside of the function as the memory pointed to by original pointer is same as the one pointed by res
. This is also why writing 'j'
to c[2]
changes original array:
c[2] = 'j'; /* note: this is same as *(c + 2) = 'j'; and this is why it works - you
are using memory pointed to by pointer */
If you need to change the pointer itself you need to pass address to that pointer instead:
void func(char *c, int size, char **res)
Upvotes: 1