I want to pass a char pointer to a function and have it set the value and pass it back. Here is my attempt but the printf prints garbage, where am I going wrong?
int a() {
char *p;
b(p);
printf("%s", p);
return 0;
}
int b(char * ptr) {
ptr = "test string";
return 0;
}
Pass a reference to the pointer.
int b(char **ptr)
{
*ptr = "Print statement";
//your code
}
//call
b(&p);
If you want to set the value of the pointer and pass it back, then b() needs to return a pointer:
int a(void) {
char *p = NULL;
p = b(p);
printf("%s", p);
return 0;
}
char * b(char * ptr) {
ptr = "test string";
return ptr;
}
Here p is initialized to NULL to avoid undefined behavior from passing an uninitialized value to a function. You could also initialize p to another string literal. Inside b, ptr is a copy of the pointer p that was passed to b. When you reassign the value stored in ptr to the address of the string literal "test string", the original pointer p is unchanged. By passing ptr back to the calling function, and reassigning p to the return value of b, the calling function can use the updated value.
As #M.M points out in the comments, this is somewhat redundant. The function b() could instead declare a pointer of its own, initialized to a string literal:
int a(void) {
char *p = b();
printf("%s", p);
return 0;
}
char * b(void) {
char *ptr = "test string";
return ptr;
}
Related
After calling f() on ptr, I expect it to point to a single byte with value of A.
But instead ptr is copied by value and it is only available in the f function(?)
What am I doing wrong?
void f(char* ptr) {
ptr = (char*) malloc(1);
*ptr = 'A';
}
int main() {
char* ptr;
f(ptr);
printf("%c\n", *ptr); // Segmentation fault, But it should be 'A'
// free(ptr);
}
Thanks!
Yes, it's passed by value. If you want the changes you make to the pointer to be visible at the call site, you need to pass a pointer to the pointer.
Example:
#include <stdlib.h>
#include <stdio.h>
void f(char **ptr) { // pointer to the pointer
*ptr = malloc(1);
if(*ptr) // precaution if malloc should fail
**ptr = 'A';
}
int main(void) {
char *ptr;
f(&ptr); // take the address of `ptr`
if(ptr) // precaution again
printf("%c\n", *ptr); // now fine
free(ptr); // without this, you have a memory leak
}
Or, f() could simply return the pointer.
Form the habit of testing return values.
#include <stdio.h>
#include <stdlib.h>
char *f(void) {
char *ptr = malloc(1);
if( ptr != NULL )
*ptr = 'A';
return ptr;
}
int main() {
char *ptr = f();
if( ptr != NULL )
printf( "%c\n", *ptr );
free( ptr );
}
You might even be able to save some code if you write main() like this:
int main() {
char *ptr;
if( ( ptr = f() ) != NULL )
printf( "%c\n", *ptr ), free( ptr ), ptr = NULL;
/* more code that will see ptr as NULL */
}
And, that leads to this (being inefficient but valid):
int main() {
for( char *ptr = f(); ptr; free( ptr ), ptr = NULL )
printf( "%c\n", *ptr );
}
You are passing the pointer ptr to the function f() by value.
This essentially means that the pointer variable you passed to f() will be copied locally inside f().
Any changes made to the local copy will only affect the local copy and not the original variable you passed to f().
When a variable is passed by value, it's copy can be referenced by whatever the function argument is called.
In your case, the pointer you pass to f() has been copied inside f() and the local copy can be referenced by ptr, since that is the argument name in:
void f(char *ptr)
Now you know how pass by value works you may now understand why your code is erroneous.
In the code:
void f(char* ptr) {
ptr = (char*) malloc(1);
*ptr = 'A';
}
You modify a local copy of what you passed into f() called ptr. And since it is local, it has something called automatic storage duration.
Automatic storage duration essentially means that after the function ends, all local variables will cease to exist and the memory they occupy will be freed. This means your code actually causes a memory leak because the pointer to the memory you allocated is lost.
Solution:
In order to achieve what you want and to modify the pointer called ptr declared in main() you must pass the address of the pointer you want to modify.
This would look like this:
void f(char **ptr)
{
*ptr = malloc(sizeof(char));
if (*ptr == NULL)
{
fprintf(stderr, "malloc fail");
return;
}
**ptr = 'A';
}
int main()
{
char *ptr;
f(&ptr);
printf("%c\n", *ptr);
return 0;
}
Output:
A
Function parameters are its local variables. Changing a local variable has no effect on the argument expression.
You can imagine the function definition and its call the following way
int main() {
char* ptr;
f(ptr);
printf("%c\n", *ptr); // Segmentation fault, But it should be 'A'
// free(ptr);
}
void f( /*char* p */ ) {
char *p = ptr;
p = (char*) malloc(1);
*p = 'A';
}
That is the function parameter p (I renamed it to distinguish the parameter and argument in the function call) is initialized by the value of the argument expression and within the function the local variable p that occupies its own extent of memory is changed.
To change the original pointer you need to pass it to the function by reference. In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the pointer you get a direct access to the original object.
So the function in your program should be defined the following way
void f(char **ptr) {
*ptr = (char*) malloc(1);
**ptr = 'A';
}
and called like
f( &ptr );
you are passing a address of ptr so this will be copied to the funktion f(),
a smiple solution can be: you make the f(...) return a char* and used in the main: ptr = f(ptr);
Alternatively, you can allocate the memory for ptr where you declare it:
void f(char* ptr) {
*ptr = 'A';
}
int main() {
char* ptr = malloc(1);
f(ptr);
printf("%c\n", *ptr); // Segmentation fault, But it should be 'A'
free(ptr);
}
There is some code piece right here below:
main ()
{
char in[8];
char out[255];
iconv_t cd;
cd = iconv_open("gb18030", "utf-8");
...
char *p_in = in;
char *p_out = out;
size_t inlen = strlen(in);
size_t outlen = sizeof(out);
if (iconv(cd, &p_in, &inlen, &p_out, &outlen) < 0)
{
...
return -1
}
...
return 0;
}
I can't totally understand the 2nd and 3rd parameters of the call to iconv. Why should that be ** pointer not the * pointer as the input? Can anyone explain the cases in C when the ** pointer should be used?
Pointer to pointer is used where the passed pointer is need to be modified in the called function and that modification need to be seen in the caller function. This is required because in C arguments are passed by value. So, when an argument is passed to a function then it simply copied to the function's parameter and created a local copy having block scope. Any change to that variable will not be seen in the argument that has been passed.
void foo(in x){
x = 10;
}
int main(void){
int x = 5;
foo(x)
printf("%d\n", x); // x will be 5
}
Same happens with pointers
void bar(char *p){
p = "foobar";
}
int main(void){
char *p = NULL;
bar(p);
if(p)
printf("p is pointing to %s\n", p);
else
printf("p is NULL\n"); // This will
}
Using a pointer to pointer will do the desired job (pointing p to the string "foobar"
void bar(char **p){
*p = "foobar";
}
int main(void){
char *p = NULL;
bar(&p);
if(p)
printf("p is pointing to %s\n", p);
else
printf("p is NULL\n"); // This will
}
Another use is when an array of string is need to passed to a function. Like
int main(int argc, char **argv)
or
void print_fruits(char **fruits, size_t len){
for(int i = 0; i < len; i++)
printf("%s\n", fruits[i]);
}
int main(void){
char *fruits[5] = {"Apple", "Banana", "Cherry", "Kiwi", "Orange"};
print_fruits(fruits, sizeof(fruits)/sizeof(fruits[0]));
}
Note that in function call print_fruits, fruits in the argument list will decay to pointer to its first element and the expression fruits will become of type char ** after the conversion.
Let's say I have a pointer pointing to memory
0x10000000
I want to add to it so it traverses down memory, for example:
0x10000000 + 5 = 0x10000005
How would I do this inside a function? How would I pass in the address that the pointer points to, and inside the function add 5 to it, then after the function's complete, I can use that value?
You have two options:
The function can return the updated pointer.
char *f(char *ptr) {
ptr += 5;
return ptr;
}
The caller then does:
char *p = some_initialization;
p = f(p);
The function argument can be a pointer to a pointer, which it indirects through:
void f(char **ptr_ptr) {
*ptr += 5;
}
The caller then does:
char *p = some_initialization;
f(&p);
Basically, like what everyone else as said you have to pass the pointer by reference(that is a pointer to a pointer aka double pointer) to the function.
#include<stdio.h>
void IncrementAddress(void **addr)
{
int offset=5;//give what ever value you want
*addr = *addr + offset;
printf("%d\n",*addr);
}
int main()
{
char x;// or any other data type like int x or float x etc.
void *ptr=NULL;
ptr = &x;
printf("%d\n",ptr);
IncrementAddress(&ptr);
printf("%d\n",ptr);
return 0;
}
I know the c always pass by values, but if I have a pointer:
int i = 4;
int * p;
p = &i;
then I have a function, how to pass pointer p to it and change the value of variable i?
void changeValue(int *p)
{
}
how to pass the pointer and change the variable pointed by p?
This simple example shows how to pass a pointer (i.e. not a value) and recieve back through that pointer, the new value held by the integer. Note the reduced number of variables. i.e. there is no need necessarily to create a separate copy of int *p;. Nor is it necessary in this case to initialize p: p = &i; to the address of i.
int changeValue(int *);
int main(void)
{
int i=15;
changeValue(&i);
return 0;
}
int changeValue(int *p) //prototyped to accept int *
{
return *p = 3;
}
If you do want to create a pointer in the first place, and pass that pointer, then:
int changeValue(int *);
int main(void)
{
int i=15;
int *p;
p = &i;
*p; // *p == 15 at this point
//since p is already a pointer, just pass
//it as is
changeValue(p);
return 0;
}
int changeValue(int *q) //prototyped to accept int *
{
return *q = 3;
}
It is important to note that your statement: I know the c always pass by values is not correct. It is more common for functions to be written such that pointers are passed because often a pointer is smaller, and more efficient to pass around than the actual variable, especially when large arrays, or structs are used. Keep in mind though that passing &i (the address of i) works just as well as passing p if passing a pointer is called for.
Simply pass it by calling changeValue as
changeValue(p);
and change the value of variable pointed by it (i) by assigning a value to the *p in changeValue()
void changeValue(int *p)
{
*p = an int value;
}
void changeValue( int* ) ;
int main( void )
{
int i = 4; // Suppose i is stored at address 1000h
int * p;
p = &i; // Now p stores the address of i that is 1000h
changeValue(p); // Can also be written as changeValue(&i);
// Here you are passing the address of i to changeValue function
return 0 ;
}
void changeValue( int* p ) // Accept a parameter of type int*
{
*p = 100 ; // store the value 100 at address 1000h
return ;
}
int i = 4;
int * p = &i;
changeValue(p);
printf("%d",*p);
void changeValue(int *p)
{
*p = 5;
}
Full program - http://ideone.com/DCvhxE
If you dereference the pointer in changeValue and assign to it, it will alter the value of i in the calling frame.
e.g.:
void changeValue(int *p)
{
*p = 0;
}
I wrote a more complex program but I have narrowed down my problem to the following one:
Why is this program printing down junk and not hzllo? I have followed the values and memory address of temp and p with the debugger and it returns from the foo function correctly and for a reason I don't understand prints junk.
void foo(char **str) {
char temp[79];
strcpy_s(temp,79,*str);
*(temp + 1) = 'z';
*str = temp;
}
void main() {
char *p = (char*) malloc(79 * sizeof(char));
p = "hello";
foo(&p);
printf("%s", p);
}
Change
char temp[79]; # allocated on the stack, vanishes on return
...to...
static char temp[79]; # has a longer lifetime
Also, you don't need the malloc(3).
temp is a local variable, which goes out of scope when you exit foo. Thus p is a dangling pointer and your program has undefined behaviour.
void foo(char **str) {
// Bad: "temp" doesn't exist when the function returns
char temp[79];
strcpy_s(temp,79,*str);
*(temp + 1) = 'z';
*str = temp;
}
void main() {
char *p = (char*) malloc(79 * sizeof(char));
p = "hello";
foo(&p);
printf("%s", p);
}
This is better:
void foo(char **str) {
// This should change the pointer ... to something valid outside the function
*str = (*str) + 1;
}