Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why 2 stars when passing pointer to a string to a function

After a long time spent on making this code work, can someone explain to me why I need 2 stars when I pass a pointer to a string as an argument to the function? A pointer, by definition, keeps the address to a memory where a certain variable will be placed. So it is a variable that has got its own address and under this address is address to another variable. Okay. So if I pass a pointer to a function I use ampersand because I must pass the pointer address to the function. Fine. But then what happens. The function receives the information where in the memory is located this pointer. Okay. This is what I understand. What I do not understand is why I need two stars when I define the function and its argument. I am passing a pointer to a char variable. Why not void wpisuj(char * w). Why wpisuj(char** w). Memory allocation is understandeable to me - I reserved memory with malloc and malloc returns address of this memory, so I place this address as the value of the variable w. And then again something I do not understand, if *w is the pointer and keeps the address of the newly created place in the memory, why I use *w to place there a string. Should it not be *(*w)? Since *w is the address of the reserved memory, then *(*w) is the contents of this memory.

Summing up. What I do not understand is: 1) why wpisuj (char **w) instead of wpisuj (char *w) 2) why strcpy(w, bufor) instead of strcpy((*w), bufor)

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
# define SIZE 256

void wpisuj(char** pw){
  char bufor[256];
  scanf("%s", bufor);
  int l;
  l=strlen(bufor)+1;
  *pw=(char*)malloc(l*sizeof(char));
  strcpy(*pw, bufor);
}


int main(){
  char* w;
  wpisuj(&w);
  printf("%s", w);  

   return 0;
}

And if I may also ask about freeing the memory. Am I correct in thinking that this is the corect amount of stars (as in the code below):

void free_memory(char **w){
   free(*w);
}

but, if I freed memory in main() I would have:

int main(){
  w=malloc(sizeof(buffer)+sizeof(char));
/* some code before */
  free(w);
}
like image 1000
Me_me_me Avatar asked Sep 04 '25 01:09

Me_me_me


1 Answers

To make it clear consider the following simple program

#include <stdio.h>

void f( int x )
{
    x = x + 20;
}

int main(void) 
{
    int x = 10;

    printf( "Before the call f( x ) x = %d\n", x );
    
    f( x );
    
    printf( "After  the call f( x ) x = %d\n", x );
    
    return 0;
}

The output will be

Before the call f( x ) x = 10
After  the call f( x ) x = 10

As you see x was not changed in the function f because the function deals with a copy of the value of the object x defined in main.

However if you will rewrite the function the following way

#include <stdio.h>

void f( int *x )
{
    *x = *x + 20;
}

int main(void) 
{
    int x = 10;

    printf( "Before the call f( x ) x = %d\n", x );
    
    f( &x );
    
    printf( "After  the call f( x ) x = %d\n", x );
    
    return 0;
}

then in this case the output will be

Before the call f( x ) x = 10
After  the call f( x ) x = 30

because we passed to the function the address of the original object x and inside the function the original object itself was changed due to dereferencing the passed pointer.

The same is valid with the pointer from your post.

If you will define a pointer

char *p;

in main and pass it as an argument to function

void f( char *p );

then the function will deal with a copy of the original object (pointer). Any changes of the copy do not influence on the original pointer. So as in the first example you should pass a pointer to this pointer that is the function should be declared like

void f( char **p );

and you have to call it like

f( &p );
like image 92
Vlad from Moscow Avatar answered Sep 07 '25 10:09

Vlad from Moscow