-2

I am currently trying to learn how linked lists as a personal project. I understand the core concepts and I have been trying to implement it into c. My program looks like it should work, keep in mind I am still new to programming :D

I created a structer pointer called head. head will point to the first node in the linked_list and startPtr will contain the address of head. Each time the function add is called a new node will be created and allocated some space in memory then the previously created node will point to the new node.

I know where my program is crashing but I can see why? It compiles fine.

My code crashes on the line

(*prevNode)->link = newNode; 

This is the way I see this code: I pass the double pointer startPtr into the function add. I then created a new node using malloc. Next I deference startPtr ( which is called prevNode in the function ) which should contain the memory address of head....right? I then use the "->" expression to point the the structure pointer inside head called link.

The program just ends at this point and I have no idea why. I have looked at other linked list c codes but most of them don't use double pointers they just declare global structers and pointers. I am using GCC as my compiler.

Anyone know why this is happening?

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


// STRUCTURES

struct node
{
    int data;
    struct node *link;
}*head;

void add( int, struct node ** );


int main()
{   
    struct node *head;
    struct node **startPtr;
    startPtr = head;
    struct node *nodePtr;
    int userInput;
    int inputData;


    do{
    printf( "\n\n1: enter new node\n" );
    printf( "2: Print Nodes\n" );
    printf( "\n\nEnter: " );
    scanf( "%d", &userInput );
        if ( userInput == 1 )
        {
            printf( "\n\nEnter data:");
            scanf("%d", &inputData );
            add( inputData, startPtr );
        }

    }while( userInput == 1 );

    // printing linked list
    nodePtr = head->link;
    while( nodePtr->link != NULL )
    {
        printf( "%d\n", nodePtr->data);
        nodePtr = nodePtr->link;
    }
    printf( "%d\n", nodePtr->data);
    return 0;

}// END main()

void add( int num, struct node **prevNode )
{
    // assigning memory for a new node
    struct node *newNode = malloc( sizeof( struct node ) );
    (*prevNode)->link = newNode;        
    newNode->data = num;        
    newNode->link = NULL;        
    prevNode = &newNode;
}// END add()

Also I have one other question which I couldn't find and answer to online. when I create a pointer to a structer e.g. struct node *ptr;. does the structer pointer my default store the address of it's self. by its self I mean the structer, so if I print ptr will it output the address of the structer ptr?

5
  • Aside from head being uninitialized, your add() function is also bugged (it's assignment to prevNode does not change the caller's variable).
    – jarmod
    Commented Oct 10, 2017 at 13:24
  • Yeah sorry, I was messing around with it the morning and I must of deleted it by accident. I have edited my code. I am new to coding so I am not sure what you mean by that. I thought because I passed a pointer all changes made in the function would be written to a the memory location of the pointers address.
    – C. Centre
    Commented Oct 10, 2017 at 13:29
  • 1
    Why was this re-opened? How is this not a duplicate of "I'm trying to store data to the address of an unitinialized pointer"? We don't need to explain why that doesn't make sense 10 times per day. Canonical duplicates exist for a reason.
    – Lundin
    Commented Oct 10, 2017 at 13:32
  • startPtr = head is btw not even valid C. Ok so this code won't even compile. We really needed to re-open this question, right...
    – Lundin
    Commented Oct 10, 2017 at 13:33
  • Also the now edited version with a global head makes even less sense. This global variable is shadowed by a local variable. Commented Oct 10, 2017 at 13:39

3 Answers 3

2

A lot to unpack here... these are uninitialized and then you alias a pointer rather than point to an address so you really don't have a pointer to a pointer you have 2 of the same pointer

struct node *head;
struct node **startPtr;
startPtr = head;
struct node *nodePtr;

maybe something like this:

struct node *head = NULL;
struct node **startPtr = &head;
struct node *nodePtr = NULL;

would be a better start... then in C you can't deref a NULL pointer so you have to check first if there is a possibility of a null pointer... note this wont check for uninitialized garbage values, which local variable can be:

if(startPtr && *startPtr)
{
 // now you know you can deref startPtr twice,  
 // once to a pointer to an object (which might be null)
 // then after then && you can deref to an actual object
}
1
  • startPtr = head; is not even valid C. These are not compatible pointer types. The line is a constraint violation of simple assignment.
    – Lundin
    Commented Oct 10, 2017 at 13:40
1

Apart from this typo

startPtr = head;
           ^^^^

where has to be

startPtr = &head;
           ^^^^^  

there are several problems with the code.

The first one is that the header was not initialized initially. So dereferencing this pointer results in undefined behavior.

The second problem is that this loop

do{
printf( "\n\n1: enter new node\n" );
printf( "2: Print Nodes\n" );
printf( "\n\nEnter: " );
scanf( "%d", &userInput );
    if ( userInput == 1 )
    {
        printf( "\n\nEnter data:");
        scanf("%d", &inputData );
        add( inputData, startPtr );
    }

}while( userInput == 1 );

is built logically incorrectly. For example if the user enters some number that is not equal to 1 or 2 then the program will try to output the list after exiting the loop.

The third one is as initially the header can be equal to null. So this statement in the function

(*prevNode)->link = newNode;

again invokes undefined behavior and moreover if *prevNode is not equal to NULL then all early appended nodes will be lost because its reference link is overwritten.

The function can look the following way

int add( struct node **head, int data )
{
    struct node *newNode = malloc( sizeof( struct node ) );
    int success = newNode != NULL;

    if ( success )
    {
        newNode->data = data;
        newNode->link = *head;
        *head = newNode;
    }

    return success;
}
2
  • The first problem is that the code doesn't compile in the first place, since it isn't valid C. startPtr = head; These are not compatible pointer types. The line is a constraint violation of simple assignment.
    – Lundin
    Commented Oct 10, 2017 at 13:41
  • @Lundin I think it is just a typo because as it follows from its post there was a segmentation fault. Commented Oct 10, 2017 at 13:46
1
struct node *head;

never initialized

startPtr = head;

initialized to uninitialized; your entire program is undefined beyond this point.

1

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.