cpointersstructstackstrcpy

Why does pointer to custom struct doesn't work here?


  1. Why pointer to custom struct doesn't work in that code?
  2. Why I'm getting warning in that line with p->x = x?
  3. Why I'm getting second warning in line with strcpy_s?
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct sptr {
    int x;
    char* s;
    struct sptr* next;
} ptr;

void add(ptr* p, int x, const char* s) {
    ptr* o = p;
    p = (ptr*) malloc(sizeof(ptr));
    p->x = x; // warning
    p->s = (char*)malloc(20 * sizeof(char));
    strcpy_s(p->s, 20, (char*)s); // warning
    p->next = o;
}

void show(ptr* p) {
    ptr* o = p;
    while (o != NULL) {
        printf("%d %s\n", o -> x, o -> s);
        o = o->next;
    }
}

int main() {
    ptr* p = NULL;

    add(p, 5, "xcvxvxv");
    add(p, 7, "adadad");
    show(p);

    return 0;
}

Solution

  • Pointers are values.

    add is receiving a copy of the NULL pointer value. Changing the local variable p, in add, to a new pointer value returned by malloc does not change the separate, local variable p in main.

    Just as if you wanted to change the value of an int in the caller's scope, you'd use an int * argument:

    void change(int *val)
    {   
        *val = 10;
    }                   
                                    
    int main(void)             
    {
        int a = 5;             
        change(&a);
    }
    

    Changing the value of an int * in the caller's scope would require an int ** argument.

    #include <stdlib.h>
    
    void change(int **val)
    {
        *val = malloc(sizeof **val);
    }
    
    int main(void)
    {
        int *a;
        change(&a);
    }
    

    This extends to any type.


    malloc can fail, and return NULL. Performing indirection on a NULL pointer value is Undefined Behaviour.

    You must guard against this happening by checking the return value of malloc.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct node {
        int x;
        char *s;
        struct node *next;
    } Node;
    
    void add(Node **p, int x, const char *s) {
        Node *new_node = malloc(sizeof *new_node);
    
        if (!new_node) {
            perror("allocating node");
            exit(EXIT_FAILURE);
        }
    
        new_node->s = malloc(1 + strlen(s));
    
        if (!new_node->s) {
            perror("allocating node string");
            exit(EXIT_FAILURE);
        }
    
        new_node->x = x;
        strcpy(new_node->s, s);
    
        new_node->next = *p;
        *p = new_node;
    }
    
    void show(Node *p) {
        while (p) {
            printf("%d %s\n", p->x, p->s);
            p = p->next;
        }
    }
    
    int main(void) {
        Node *list = NULL;
    
        add(&list, 5, "xcvxvxv");
        add(&list, 7, "adadad");
    
        show(list);
    }