Thread: Issue with Structs

  1. #1
    Registered User
    Join Date
    Mar 2008
    Posts
    25

    Issue with Structs

    Hi,

    I just wanted to clear something up regarding structs.

    Why is it that I can declare a strut like this:

    Code:
    typedef struct date_header {
    	uint16_t year;
    	uint8_t month;
    	uint8_t day;
    
    } DATE;
    And do this kind of thing without any problems:

    Code Segement 1:

    Code:
    DATE *datePtr; 
    uint8_t rx_buffer[4]; 
    
    // assume the rx_buffer has been filled with 4 bytes of data at this point
    
    datePtr = (DATE *)rx_buffer;
    
    printf("Year is: %d", datePtr->year);
    However, if I do this:


    Code Segment 2:


    Code:
     DATE *datePtr; 
    
    datePtr->year = 1;
    datePtr->month = 2;
    datePtr->day = 3;
    
    printf("Year is: %d", datePtr->year);
    It gives me a segmentation fault at the point where year is being assigned a value.

    For some reason, doing this works:

    Code Segment 3:
    Code:
    DATE date, *datePtr; 
    
    datePtr = &date;
    
    datePtr->year = 1;
    datePtr->month = 2;
    datePtr->day = 3;
    
    printf("Year is: %d", datePtr->year);
    How come I don't need to declare:
    Code:
    DATE date, *datePtr; 
    
    datePtr = &date;
    for the code in segment 1?

    Thanks.

  2. #2
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    The reason it crashes in segment two is because you've only created a pointer to the struct, but not allocated memory for it. It could point anywhere - even read-only memory, in which you are trying to write = crash.

    Anyway, the reason you don't have to allocate memory in the first is because you've made the struct pointer point to the array, which is allocated data. In segment three, you declare an instance of the struct, not a pointer to it - eg, the struct is allocated on the stack and is this valid memory. You then make the pointer point to that struct, thus making it point to valid memory.

  3. #3
    Registered User
    Join Date
    Mar 2008
    Posts
    25
    Thanks for your amazingly fast reply!

    That make perfect sense now.

    Do you also know how I could string together the following to make one argument
    to pass to sendto() which takes a message in the form
    Code:
    const void *buffer
    ?

    Code:
    DATE date, *datePtr; 
    uint8_t options[100];
    uint8_t message[100];
    
    datePtr = &date;
    
    // date is filled with data
    // options is filled with data
    // message is filled with data
    I've tried simply passing:

    Code:
    (datePtr + options + message)
    as the argument to the function, but I was doubtful from the beginning that it would work.

    I just get a message "Invalid operands to binary +".

    I know Java can string together stuff like this with all sorts, but I was doubtful C could.

  4. #4
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    make one big buffer and fill it withall the data you need to send (using sprintf for example)
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You can, but it depends on what you want to do.
    With strings, you can append them using strcat.
    If it's plain memory, you can place them after each other in a buffer using memcpy.
    But if you just put everything on the stack after each other, like your example, then all you have to do is pass the address of the first variable.
    Since they're placed after each other in memory, it works just as well. But the function you're passing it to need to be aware of exactly how long (or big) the buffer is, because it cannot say. And if it thinks it's bigger than it really is, it can read or overwrite data that it shouldn't.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    But if you just put everything on the stack after each other, like your example, then all you have to do is pass the address of the first variable.
    Very bad idea...
    You cannot know if addresses of local vars are going Up or Down
    You cannot know if there is some space in addresses between two vars
    And also you intend to increment the starting address outside the first array - whic results in undefined behaviour... So NO, never do it!
    If you do not want to use everything into a string - use one struct at least with all info presented as its members
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Agreed. A bad idea. You should never be working with raw memory, if possible, anyway.
    And I don't fancy a it a good idea to slam those 3 variables together either. Just pass the 3 variables as 3 arguments.
    Easiest. Fastest. Securest.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Mar 2008
    Posts
    25
    Code:
    #include <sys/socket.h>
    
    ssize_t sendto(int socket, const void *message, size_t length,
           int flags, const struct sockaddr *dest_addr,
           socklen_t dest_len);
    With that definition, I cannot pass datePtr, options and message as three different arguments.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You can do the function call 3 times.
    Otherwise allocate another buffer and copy them together.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Registered User
    Join Date
    Mar 2008
    Posts
    25
    Otherwise allocate another buffer and copy them together.
    Could you please give me an example of how you would do this?
    Thanks!

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    DATE date;
    uint8_t options[100];
    uint8_t message[100];
    
    void* pBuffer = malloc(sizeof(date) + sizeof(options) + sizeof(message));
    memcpy(pBuffer, &date, sizeof(date));
    memcpy(pBuffer + sizeof(date), options, sizeof(options));
    memcpy(pBuffer + sizeof(date) + sizeof(options), message, sizeof(message));
    /* Do whatever */
    free(pBuffer);
    I think.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Mar 2008
    Posts
    25
    Thanks all!

  13. #13
    Registered User
    Join Date
    Mar 2008
    Posts
    25
    hmm slight problem:

    I have this kind of thing:

    Code:
    int some_function(char *message) {
    
    DATE tx_header;
    uint8_t options[64]; // this isn't always totally full (normally only the first two elements) so hence the strlen below:
    
    void* tx_buffer = malloc(sizeof(tx_header) + strlen(options) + strlen(message));
    	
    // fill the transmit buffer
    memcpy(tx_buffer, &tx_header, sizeof(tx_header));
    memcpy(tx_buffer + sizeof(tx_header), options, strlen(options));
    memcpy(tx_buffer + sizeof(tx_header) + strlen(options), message, strlen(message));
    	
    printf("strlen(options): &#37;d\n", strlen(options));
    printf("strlen(message): %d\n", strlen(message));
    printf("sizeof(tx_header) is : %d\n", sizeof(tx_header));
    	
    printf("sizeof(tx_buffer) is: %d, strlen(tx_buffer) is: %d\n", sizeof(tx_buffer), strlen(tx_buffer));
    
    }
    this gives the following output with a message of :"the quick" (minus quotes):

    Code:
    strlen(options): 2 // two options
    strlen(message): 10 // 9 characters plus the \n
    sizeof(tx_header) is : 12 // this should be twelve (this is a differen't struct to the one in the first post)
    sizeof(tx_buffer) is: 4, strlen(tx_buffer) is: 9 // what the hell?
    Last edited by eponymous; 03-16-2008 at 11:55 AM.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Strlen is only used to get the length of strings.
    If you need to get the length of how many elements in an array you've filled, you must manually keep track of it.
    Sizeof can be used on arrays to calculate the total size of the array.
    However, when used on a pointer, it returns the size of the pointer, or if you dereference it, the size of one element.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User
    Join Date
    Mar 2008
    Posts
    25
    Both options and message are strings, so I don't see the problem. I pass in a char line_buf[300] as the argument to the function, so I'd assume strlen would be ok for this?

    The point I'm trying to make is that:

    Code:
    strlen(options): 2 // two options
    strlen(message): 10 // 9 characters plus the \n
    sizeof(tx_header) is : 12 // this should be twelve (this is a differen't struct to the one in the first post)
    is fine and is what I would expect.

    it's just:

    Code:
    sizeof(tx_buffer) is: 4, strlen(tx_buffer) is: 9 // what the hell?
    which is confusing.

    I was expecting tx_buffer to be 24 in length (or 25 including a \0)

    I basically need to return the length of tx_buffer as a sum of bytes of all the strings and headers in it.

    Any ideas?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Creating array of structs
    By knirirr in forum C++ Programming
    Replies: 12
    Last Post: 06-18-2008, 08:30 AM
  2. Multidimentional structs + memcpy() == FAIL
    By Viper187 in forum C Programming
    Replies: 8
    Last Post: 06-18-2008, 02:46 AM
  3. float calculation issue
    By George2 in forum C# Programming
    Replies: 1
    Last Post: 05-26-2008, 04:56 AM
  4. ArrayLists + Inner Structs
    By ginoitalo in forum C# Programming
    Replies: 5
    Last Post: 05-09-2002, 05:09 AM
  5. Searching structs...
    By Sebastiani in forum C Programming
    Replies: 1
    Last Post: 08-25-2001, 12:38 PM