Why 2 stars when passing a pointer to a function string

After spending a long time getting this code to work, can someone please explain to me why I need 2 stars when I pass a pointer to a string as an argument to a function? A pointer, by definition, stores an address in memory where a particular variable will be placed. Thus, it is a variable that has its own address and at this address addresses another variable. Good. So if I pass a function pointer, I use an ampersand because I have to pass the address of the function pointer. Good. But then what happens. The function gets the information in which this pointer is located in memory. Good. This is what I understand. I don't understand why I need two stars when I define a function and its argument. I am passing a pointer to a char variable. Why not void wpisuj (char * w). Why is wpisuj (char ** w).The memory allocation is clear to me - I have reserved memory with malloc, and malloc returns the address of this memory, so I put this address in the value of the w variable. And again something I don't understand if * w is a pointer and stores the address of the newly created location in memory, why am I using * w to place a string there. If it won't be * (* w)? Since * w is the address of the reserved memory, then * (* w) is the contents of this memory.then * (* w) is the contents of that memory.then * (* w) is the contents of that memory.

Summarizing. I don't understand what: 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 can ask about freeing memory. Am I correct in assuming that this is the number of stars (as in the code below):

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

      

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

int main(){
  w=malloc(sizeof(buffer)+sizeof(char));
/* some code before */
  free(w);
}

      

+3


source to share


5 answers


For this it would be clear that 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 can see, x was not tagged with the function f, because the function deals with a copy of the object x defined in main.

However, if you rewrite the function like this

#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 the function the address of the original object x and inside the function in which the original object was modified.



The same goes for the pointer from your post.

If you give a pointer

char *p;

      

in main and pass it as a function argument

void f( char *p );

      

then the function will deal with a copy of the original object. Any changes made to the copy do not affect the original pointer. Since in the first example you need to pass a pointer to this pointer, which is a function, must be declared as

void f( char **p );

      

and you have to call it like

f( &p );

      

+5


source


The reason being wpisuj

passed char**

is that when memory is allocated in a function and assigned to *w

, the change is reflected in the calling function when it returns from wpisuj

.

If you have:



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

      

Change to w

is only a local change. The caller does not see the change.

+4


source


Ok, I'll explain what I understood from your question: Whenever you want to use a function to change your variable, you need to send its address, otherwise inside your function you will change the local copy (local to the function) and as soon as it returns , she will be lost.

1) Basically, in the main , you create a pointer that points to nothing, and you call a function wpisuj()

to point to something. Using the idea above, you should send the memory position of your pointer so that the function can change where it points. If you sent only w

instead &w

, you would send a copy of the address to where he indicated and you could not change it.

2) Your function strcpy

expects a specific input, which is the address string

, not the address of your pointer. Hence, you use *w

to find what your w

.

0


source


The code below shows another way to do the same. The main difference is that the function wpisuj

returns a pointer to the newly allocated string (which main

then assigns w

). This method avoids the use of a pointer to a pointer because you wpisuj

don't need to modify the main's

copy w

.

Other differences

  • error checking: marked return values ​​from scanf

    andmalloc

  • no memory leaks: free( w )

    at the end
  • better security: %255s

    to scanf

    prevent the user buffer overflow

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *wpisuj( void )
{
    char bufor[256];

    if ( scanf( "%255s", bufor ) != 1 )
        return( NULL );

    char *w = malloc( strlen(bufor) + 1 );

    if ( w != NULL )
        strcpy( w, bufor );

    return( w );
}

int main()
{
    char *w;

    if ( (w = wpisuj()) != NULL )
    {
        printf( "%s\n", w );
        free( w );
    }

    return 0;
}

      

0


source


Why do I need a double pointer?

Here is what I understand your question. The answer is this: since, like all actual parameters (which copy the value passed by the caller), the pointers passed to the function will store their values ​​in the scope in which they were actually declared (which in this case is the scope of the called function) without changing nothing in the caller function. And that's not what you want, because you want to change the value w

.

If you do something like this:

void MyFunction(int* p) {
    //`p` value, like `a` value, is NULL
    *p=(char *)malloc(256*sizeof(char));
    //`p` value is the starting address of the buffer, but `a` didn't change
    return;
}

int main() {
    char* a;
    a=NULL;
    MyFunction(a);
    return 0;
    //`a` value is still NULL, because MyFunction() changed only its own copy of `a`
}

      

Nothing happens because you are just changing the address given p

inside MyFunction()

.

So, as for integers:

void MyFunction(int* p) {
    *p=1;
    return;
}

int main() {
    int a;
    a=0;
    MyFunction(&a);
    printf("%d", a);
    return 0;
}

      

do the same for pointers:

void MyFunction(int** p) {
    *p=(char *)malloc(256*sizeof(char));
    return;
}

int main() {
    char* a;
    a=NULL;
    MyFunction(&a);
    return 0;
}

      

I don't understand why I need two stars when I define a function and its argument. I am passing a pointer to a char variable.

Why not void wpisuj (char * w). Why is wpisuj (char ** w).

Look at your code:

wpisuj(&w);

The symbol here plays out the pointer w

. This means that the entire expression &w

has an address value w

. So you are passing the address of a pointer to a char variable, which is a pointer to a pointer to a char variable. What's right: if you need to change an integer, you are passing the address of the integer. If you need to change the pointer, you pass the address of the pointer. And therefore it is even correct to use wpisuj(char** w)

.

And again something I don't understand if * w is a pointer and stores the address of the newly created location in memory, why am I using * w to place a string there.

Since you are not putting the string: if w

(inside wpisuj()

) as above is a pointer to a pointer to char, *w

(inside wpisuk()

) is a pointer to char, which is equivalent to *(&w)

in main()

, which is the value w

in main()

. So what you do is you assign the return value to the malloc()

pointer w

in main()

.

0


source







All Articles