Thread: Structures and pointers to structures

  1. #1
    Registered User
    Join Date
    May 2015
    Posts
    90

    Structures and pointers to structures

    Hey, I'm stuck when trying to make this code work, I get SIGSEGV, now I'm sure it is because I havn't defined the structures I'm trying to modify, but how am I supposed to define them?
    Say in the function, if I have to define the structure, then I would need to pass the argument of the function as a double-pointer, thus changing the address of both the copy and the actual pointer, but that doesn't seem to work either. How can I work this out?

    This is the code that passes the pointer as a copy, and SIGSEGVs:
    Code:
    typedef struct {
        size_t id;
        float mn;
        char name[256];
    } client_t;
    
    void function(client_t *pclient);
    
    int main(void) {
    
        client_t *client;
        
        printf("%p \n", client);
        printf("%i \n", client->id);
        printf("%f \n", client->mn);
        printf("%s \n", client->name);
        
        function(client);
        
        printf("%p \n", client);
        printf("%i \n", client->id);
        printf("%f \n", client->mn);
        printf("%s \n", client->name);
        return EXIT_SUCCESS;
    }
    
    
    void function(client_t *pclient) {
        pclient->id = 3;
        pclient->mn = 35.43;
        strcpy(pclient->name, "hola");
    }
    This is the code that passes it as a double pointer and has everything defined a priori, but when printing pclient for the second time it doesn't show the supposedly modified results.
    Code:
    int main(void) {
    
        client_t *pclient;
        client_t client;
        pclient = &client;
        
        printf("%p \n", pclient);
        printf("%i \n", pclient->id);
        printf("%f \n", pclient->mn);
        printf("%s \n", pclient->name);
        
        function(&pclient);
        
        printf("%p \n", pclient);
        printf("%i \n", pclient->id);
        printf("%f \n", pclient->mn);
        printf("%s \n", pclient->name);
        return EXIT_SUCCESS;
    }
    
    
    void function(client_t **pclient) {
        
        client_t client;
        *pclient = &client;
        
        (*pclient)->id = 3;
        (*pclient)->mn = 35.43;
        strcpy((*pclient)->name, "hola");
    }
    I'm not sure how to work with pointers, structures and functions at all, I mean I was doing fine with other data types (int, float, char, etc) when using pointers with functions but structures don't seem to be working out for me. I'm clueless.

    -> The identation is OK, somethings off when c&p.
    Last edited by Fiskker; 06-14-2015 at 03:38 PM.

  2. #2
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    In the 1st code, you are trying to dereference the client pointer without having it associated with allocated memory first.

    Try, either...
    Code:
    ...
    int main( void )
    {
        client_t *client = calloc( 1, sizeof(*client) );
        if ( NULL == client ) {
            return EXIT_FAILURE;
        }
        ...
        function( client );
        ...
        free( client );
        return EXIT_SUCCESS;
    }
    Or...
    Code:
    ...
    int main( void )
    {
        client_t client = {0, 0.0f, ""};
        ...
        function( &client );
        ...
        return EXIT_SUCCESS;
    }
    Additionally, in the 2nd code, inside function() you are assigning pclient to the memory of a local variable, which gets destroyed after the function exits.
    Last edited by migf1; 06-14-2015 at 04:33 PM. Reason: calloc instead of malloc
    "Talk is cheap, show me the code" - Linus Torvalds

  3. #3
    Registered User
    Join Date
    May 2015
    Posts
    90
    Hey, thanks for your reply, I'm not sure I understand you though.
    In my next code I did ask for memory with a ptr to 10 structures, then I went to every one of those structures and added something but I still get SIGSEGV.. I've no idea what to do, I have already asked for memory to 10 structs, I'm thinking maybe I have to define the type of struct somehow..?
    Code:
    int main(void) {
        cliente_t **ptr_cliente;
        char buffer[500];
        size_t i;
        
        strcpy(buffer, "1, 3.456, \"DFGH\" ");
        if((*ptr_cliente = (cliente_t *)malloc(sizeof(cliente_t)*10)) == NULL) {
            return EXIT_FAILURE;
        }
        
        for(i = 0; i < 10; i++) {
            function(((*ptr_cliente)+i), buffer);
            printf("%i \n", ((*ptr_cliente)+i)->id);
            printf("%f \n", ((*ptr_cliente)+i)->mn);
            printf("%s \n", ((*ptr_cliente)+i)->name);
        }
        
        return EXIT_SUCCESS;
    }
    
    
    void function(cliente_t *pclient, char buffer[]) {
        int number;
        char *token, *end;
        
        token = strtok(buffer, ",");
        number = strtol(token, &end, 10);
        pclient->id = number;
        
        token = strtok(NULL, ",");
        number = strtod(token, &end);
        pclient->mn = number;
        
        token = strtok(NULL, ",");
        strcpy(pclient->name, token);
    }
    This prints once and then dies, also the floating number gets passed as 3.000.. instead of 3.456

    Also don't pay attention to the fact I'm using a double-pointer this is just part of a larger program.

  4. #4
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    Quote Originally Posted by Fiskker View Post
    ...
    Also don't pay attention to the fact I'm using a double-pointer this is just part of a larger program.
    But the double pointer is a problem here! Perhaps I can be of more help if you describe with more details what you are trying to do.
    "Talk is cheap, show me the code" - Linus Torvalds

  5. #5
    Registered User
    Join Date
    May 2015
    Posts
    90
    Quote Originally Posted by migf1 View Post
    But the double pointer is a problem here! Perhaps I can be of more help if you describe with more details what you are trying to do.
    Just trying to load stuff in every structure.
    I ask for memory for (in this case) 10 structures.
    Then I copy what's inside the buffer (which is actually a fgets reading lines in the actual program)
    After that I use this damn function (: and copy that data in the i-structure (i- for "number i")

    The use of the double-pointer is because I need to pass it to the main function as a pointer (the function returns an enum type with its possible errors).
    How is the double-pointer a problem though? I'm just working with the "simple" pointer in it.

  6. #6
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    Quote Originally Posted by Fiskker View Post
    Just trying to load stuff in every structure.
    I ask for memory for (in this case) 10 structures.
    Then I copy what's inside the buffer (which is actually a fgets reading lines in the actual program)
    After that I use this damn function (: and copy that data in the i-structure (i- for "number i")

    The use of the double-pointer is because I need to pass it to the main function as a pointer (the function returns an enum type with its possible errors).
    How is the double-pointer a problem though? I'm just working with the "simple" pointer in it.
    I'm not clear on why you are using a double-pointer.

    But first things first. If you need memory for 10 client_t structures, what I understand is that you want an array, say "clients". This array can be either allocated statically in the stack:
    Code:
    client_t clients[10];
    or dynamically in the heap:
    Code:
    client_t *clients = calloc(10, sizeof(*clients));
    I take it you are interested on the latter.

    Either way, you may pass this array to any function either by value:
    Code:
    foo1( clients); // prototype: foo( client_t *clients );
    or by pointer (lets say by reference):
    Code:
    foo2( &clients); // prototype: foo( client_t **pclients );
    foo1 will treat it inside as a pointer to client_t and foo2 will treat it inside as a double pointer to client_t.

    Moreover, if a function needs to return the address of the array, then if it expects the array to be passed by value, then it will: return &clients. If it expects the array to be passed by pointer, then it will: return clients;
    Last edited by migf1; 06-14-2015 at 05:52 PM. Reason: fixed the type to: client_t
    "Talk is cheap, show me the code" - Linus Torvalds

  7. #7
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    Btw, the following code creates dynamically an array of 10 client_t structurs, fill them all with the same values (via client_set_hola()) and prints them out (via client_dump()):

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct {
        size_t id;
        float mn;
        char name[BUFSIZ];
    } client_t;
     
    void client_set_hola( client_t *client )
    {
        if ( NULL == client ) {
            fprintf( stderr, "%s: NULL pointer argument\n", __func__ );
            return;
        }
    
        client->id = 3;
        client->mn = 35.43;
        strncpy( client->name, "hola", BUFSIZ-1 );
    }
    
    void client_dump( const client_t *client )
    {
        if ( NULL == client ) {
            fprintf( stderr, "%s: NULL pointer argument\n", __func__ );
            return;
        }
    
        printf( "0x%p\n", client );
        printf( "%i\n", client->id );
        printf( "%f\n", client->mn );
        puts( client->name );
    }
    
    int main( void )
    {
        client_t *clients = calloc( 10, sizeof(*clients) );
        if ( NULL == clients ) {
            return EXIT_FAILURE;
        }
    
        for (int i=0; i < 10; i++) {
            client_set_hola( &clients[i] );
            client_dump( &clients[i] );
        }
    
        free( clients );
    
        return EXIT_SUCCESS;
    }
    Last edited by migf1; 06-14-2015 at 05:54 PM.
    "Talk is cheap, show me the code" - Linus Torvalds

  8. #8
    Registered User
    Join Date
    May 2015
    Posts
    90
    Quote Originally Posted by migf1 View Post
    I'm not clear on why you are using a double-pointer.

    But first things first. If you need memory for 10 client_t structures, what I understand is that you want an array, say "clients". This array can be either allocated statically in the stack:
    Code:
    client_t clients[10];
    or dynamically in the heap:
    Code:
    client_t *clients = calloc(1, sizeof(*clients));
    I take it you are interested on the latter.

    Either way, you may pass this array to any function either by value:
    Code:
    foo1( clients); // prototype: foo( client_t *clients );
    or by pointer (lets say by reference):
    Code:
    foo2( &clients); // prototype: foo( client_t **pclients );
    foo1 will treat it inside as a pointer to client_t and foo2 will treat it inside as a double pointer to client_t.

    Moreover, if a function needs to return the address of the array, then if it expects the array to be passed by value, then it will: return &clients. If it expects the array to be passed by pointer, then it will: return clients;
    Well, yeah I'm sure I understand the passing by value or reference, but I don't think that's the problem here (or is it..?), check my next code for instance, not using a double pointer, it SIGSEGVs as well.
    Code:
    int main(void) {
        cliente_t *ptr_cliente;
        char buffer[500];
        size_t i;
        
        strcpy(buffer, "1, 3.456, \"DFGH\" ");
        if((ptr_cliente = (cliente_t *)malloc(sizeof(cliente_t)*10)) == NULL) {
            return EXIT_FAILURE;
        }
        
        for(i = 0; i < 10; i++) {
            function(&(ptr_cliente[i]), buffer);
            printf("%i \n", (&(ptr_cliente[i]))->id);
            printf("%f \n", (&(ptr_cliente[i]))->mn);
            printf("%s \n", (&(ptr_cliente[i]))->name);
        }
        
        return EXIT_SUCCESS;
    }
    
    
    void function(cliente_t *pclient, char buffer[]) {
        int number;
        char *token, *end;
        
        token = strtok(buffer, ",");
        number = strtol(token, &end, 10);
        pclient->id = number;
        
        token = strtok(NULL, ",");
        number = strtod(token, &end);
        pclient->mn = number;
        
        token = strtok(NULL, ",");
        strcpy(pclient->name, token);
    }
    I'm just trying, if I have an array of 10 structures, then I loop through them, get the address of the first one, modify its fields, then go to the second one, modify its fields.. and so on. I'm passing it as a value now (I'm copying the pointer) but it doesn't matter since I'm modifying what's actually inside the pointer.. If I pointed it to any other place then that would be a problem since the actual pointer wouldn't be modifying itself.
    So taking in account that I think I'm doing that part right (And it is also doing one iteration and showing that I could load the first structure (pos 0)), I am inclined to think that:

    1) Either I am entering non-defined(?) fields in the structure thus that memory was never asked for (How do I fix this..?)
    or
    2) I'm passing non-called (as in I never allocated it) memory addresses to the function thus the first iteration works but after that the memory isn't "mine" (but I don't think this is the case..)

    I've no idea what's going on tbh.
    Last edited by Fiskker; 06-14-2015 at 06:02 PM.

  9. #9
    Registered User
    Join Date
    May 2015
    Posts
    90
    Quote Originally Posted by migf1 View Post
    Btw, the following code creates dynamically an array of 10 client_t structurs, fill them all with the same values (via client_set_hola()) and prints them out (via client_dump()):
    Well our codes (last one) are quite similar, so I don't know maybe I'm not allocating the memory well? No idea.

  10. #10
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    The problem lies in your tokenization. With the following it works:
    Code:
    typedef struct {
        long unsigned id;
        float mn;
        char name[BUFSIZ];
    } cliente_t;
    
    void function( cliente_t *pclient, char buffer[] )
    {
    #if 1
    //1, 3.456, \"DFGH\"
        sscanf( "%lu, %f, %s", &pclient->id, &pclient->mn, pclient->name );
    #else
        double number;
        char *token, *end;
        
        token = strtok( buffer, "," );
        number = strtol(token, &end, 10);
        pclient->id = number;
        
        token = strtok(NULL, ",");
        number = strtod(token, &end);
        pclient->mn = number;
        
        token = strtok(NULL, ",");
        strcpy(pclient->name, token);
    #endif
    }
    So have a look at those strtok/strtoXXX you are doing in there. I'm too tired right now to further look it up (its 3:22am here :P).
    "Talk is cheap, show me the code" - Linus Torvalds

  11. #11
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    Oh, another thing.. try to keep things simple & safe...

    Code:
    int main( void )
    {
        cliente_t *ptr_cliente = NULL;
        char buffer[500] = {'\0'};
        size_t i;
        
        strncpy( buffer, "1, 3.456, \"DFGH\" ", 500-1 );
        ptr_cliente = calloc( 10, sizeof(*ptr_cliente) );
        if ( NULL == ptr_cliente) {
            return EXIT_FAILURE;
        }
        
        for (i=0; i < 10; i++) {
            function( &ptr_cliente[i], buffer);
            printf("%i \n", ptr_cliente[i].id);
            printf("%f \n", ptr_cliente[i].mn);
            printf("%s \n", ptr_cliente[i].name);
        }
    
        free( ptr_cliente );
    
        system( "pause" );
        return EXIT_SUCCESS;
    }
    "Talk is cheap, show me the code" - Linus Torvalds

  12. #12
    Registered User
    Join Date
    May 2015
    Posts
    90
    Yeah, great it does work with sscanf..! Now I've no idea what's wrong with the strtok,etc. Thanks for the help have a gnight

  13. #13
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    No problem Btw, I've missed to put the buffer as sscanf's 1st arg in my previous post.

    For the rest, if noone else looks it up before me, or you haven't solved it yet, I'll take a look tomorrow.

    gnight to you too
    "Talk is cheap, show me the code" - Linus Torvalds

  14. #14
    Registered User
    Join Date
    May 2015
    Posts
    130
    Quote Originally Posted by migf1 View Post
    Oh, another thing.. try to keep things simple & safe...

    Code:
    int main( void )
    {
        cliente_t *ptr_cliente = NULL;
        char buffer[500] = {'\0'};
        size_t i;
        
        strncpy( buffer, "1, 3.456, \"DFGH\" ", 500-1 );
        ptr_cliente = calloc( 10, sizeof(*ptr_cliente) );
        if ( NULL == ptr_cliente) {
            return EXIT_FAILURE;
        }
        
        for (i=0; i < 10; i++) {
            function( &ptr_cliente[i], buffer);
            printf("%i \n", ptr_cliente[i].id);
            printf("%f \n", ptr_cliente[i].mn);
            printf("%s \n", ptr_cliente[i].name);
        }
    
        free( ptr_cliente );
    
        system( "pause" );
        return EXIT_SUCCESS;
    }
    Excuse me ? what does strncpy stand for? and the same with system...? never used or heard about it before!..may you elaborate?

  15. #15
    Registered User migf1's Avatar
    Join Date
    May 2013
    Location
    Athens, Greece
    Posts
    385
    system( "pause" ); is a Windows specific thing, so please ignore it (it just pauses until a key is pressed).
    strncpy(): you may use it as a safer alternative to strcpy(), because you pass the maximum count of chars to be copied from the source to the destination string. If you've made sure that your destination string has already its last element equal to '\0', then you pass strncpy the maximum size of the destination string minus 1 char (also have a look at the documentation of strncpy() ).
    Last edited by migf1; 06-14-2015 at 07:04 PM.
    "Talk is cheap, show me the code" - Linus Torvalds

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problems with Nested Structures and Arrays of Structures
    By Ignoramus in forum C Programming
    Replies: 4
    Last Post: 03-02-2010, 01:24 AM
  2. Structures, passing array of structures to function
    By saahmed in forum C Programming
    Replies: 10
    Last Post: 04-05-2006, 11:06 PM
  3. Structures, and pointers to structures
    By iloveitaly in forum C Programming
    Replies: 4
    Last Post: 03-30-2005, 06:31 PM
  4. structures with pointers to structures
    By kzar in forum C Programming
    Replies: 3
    Last Post: 11-20-2004, 09:32 AM
  5. Replies: 5
    Last Post: 04-11-2002, 11:29 AM