Search code examples
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);
    }