Thread: Mapping an array to a struct? Please help!

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    58

    Mapping an array to a struct? Please help!

    Hi everyone

    I am looking for a way to map an array of 8 bit unsigned ints onto a struct of the same size, but cannot work out how to do it... – can someone lend me a hand

    Code:
    struct dataStruct
    {
       uint8_t value1;
       uint8_t value2;
       uint8_t value3;
       uint8_t value4;
    };
    
    uint8_t data[4];
    
    int main()
    {
       // ????????????????????
       return 0;
    }
    I have previously tried casting the array to the struct type with no luck what so ever

    Many thanks indeed for any advice you can give!

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I would use copy'n'paste. Start with the line
    Code:
    struct dataStruct bob;
    bob.value1 = data[0];
    and then copy the line and change the numbers.

    Evil Programming: If you know that there's no padding in the struct, you could use memcpy.

  3. #3
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    Ah, my apologies, this was a simple example of a more complex problem I have, the data strut actually contains variables of different sizes in a specific order:

    Code:
    struct dataStruct
    {
       uint8_t value1;
       uint16_t value2;
       uint32_t value3;
       uint16_t value4;
    };
    etc...

    The values in the array are all divided up into individual uint8_ts however some of them are supposed to be 16 bit values, and some of them 32 bit etc. By loading them into the struct I wanted to recombine the larger values and pull them out when required... (I am packet processing with this code)

    Sorry if my example was misleading...

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by DavidDobson View Post
    Ah, my apologies, this was a simple example of a more complex problem I have, the data strut actually contains variables of different sizes in a specific order:

    Code:
    struct dataStruct
    {
       uint8_t value1;
       uint16_t value2;
       uint32_t value3;
       uint16_t value4;
    };
    etc...

    The values in the array are all divided up into individual uint8_ts however some of them are supposed to be 16 bit values, and some of them 32 bit etc. By loading them into the struct I wanted to recombine the larger values and pull them out when required... (I am packet processing with this code)

    Sorry if my example was misleading...
    Well, memcpy is still an option if your struct has no padding. Otherwise:
    Code:
    bob.value1 = data[0];
    bob.value2 = data[1] * 0x100 + data[2]; /* or use bitshifting if you're a bitshifting kind of guy */
    /* et cetera */
    Edit: I suppose I should add that if you want to check for padding in your struct, you can use offsetof. offsetof(dataStruct, value1) is guaranteed to be 0; the rest you'll have to check.
    Last edited by tabstop; 04-13-2008 at 01:23 PM.

  5. #5
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    Thank you for all the advice given so far! I have got this far with memcpy:

    Code:
    struct dataStruct
    {
            uint8_t var1;
            uint16_t var2;
            uint8_t var3;
            uint32_t var4;
    } bob;
    
    uint8_t data[8];
    
    int main()
    {
    
        data[0] = 0x4B;
        data[1] = 0x03;
        data[2] = 0xFF;
        data[3] = 0x04;
        data[4] = 0x01;
        data[5] = 0x03;
        data[6] = 0x02;
        data[7] = 0x4B;
    
        int i;
    
            for (i = 0; i < sizeof(data); i++) {
                memcpy( &bob +i -8, &data[i], 1);
            } // for
    
            printf("Var 1: %i\n", bob.var1); // 1 byte
            printf("Var 2: %i\n", bob.var2); // 2 bytes
            printf("Var 3: %i\n", bob.var3); // 1 byte
            printf("Var 4: %i\n", bob.var4); // 4 bytes
    
            return 0;
    }
    But am unsure where to go from here, I believe I need to increment where memcpy is writing to by 8 bits each time the loop cycles as the above only gives me one reading in var1.

    Also where would I need to add

    Code:
    offsetof(dataStruct, value1)
    To ensure I'm not getting padding? (if offsetof == 0 do...?)

    Again thank you

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    What I was thinking of was
    Code:
    memcpy(&bob, data, sizeof(data));
    which would put them all in, in one shot. But you would need to make sure that the offsets are right, otherwise things won't be aligned correctly. (And actually, you could also use sizeof to check -- if sizeof(bob) == 8, then we've not got any padding. That's easier than checking all the offsets. I don't know why I didn't think of it.)

    However, if there's padding you could do separate memcpy's to make sure you honor the padding your compiler has chosen for you:
    Code:
    memcpy(&bob + offsetof(dataStruct, var1), &data[0], sizeof(bob.var1));
    memcpy(&bob + offsetof(dataStruct, var2), &data[1], sizeof(bob.var2));
    memcpy(&bob + offsetof(dataStruct, var3), &data[3], sizeof(bob.var3));
    memcpy(&bob + offsetof(dataStruct, var4), &data[4], sizeof(bob.var4));
    This has the advantage of working despite whatever the layout of dataStruct is.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Due to the padding (which there almost certainly will be), the first method of memcpy is not recommended.
    But the second method is just the same as assigning data directly.

    To ensure I'm not getting padding? (if offsetof == 0 do...?)
    Note that code will not prevent padding. To prevent padding, you must tell the compiler not to use any via compiler options.
    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
    Feb 2008
    Posts
    58

    update

    Hi

    I have got the following to work (sort of) but it's still not quite right, I get the following output:

    4B 04FF 01 000000

    Process returned 0 (0x0) execution time : 0.036 s
    Press any key to continue.
    What I wanted was:

    4B 03FF 04 0103024B

    Not really what I wanted (am I suffering from a padding issue here?) and if so does anyone know how to resolve it (as in how to I tell the compiler not to use padding)?

    Thanks

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    
    void process_packet();
    
    struct dataStruct {
        uint8_t var1;
        uint16_t var2;
        uint8_t var3;
        uint32_t var4;
    } bob;
    
    uint8_t data[8];
    
    int main()
    {
    
        data[0] = 0x4B;
        data[1] = 0x03;
        data[2] = 0xFF;
        data[3] = 0x04;
        data[4] = 0x01;
        data[5] = 0x03;
        data[6] = 0x02;
        data[7] = 0x4B;
    
        process_packet();
    
        return 0;
    }
    
    void process_packet() {
    
        if (sizeof(data) == 8) {
    
            memcpy(&bob, data, sizeof(data));
    
            printf("%02X ", bob.var1);
            printf("%04X ", bob.var2);
            printf("%02X ", bob.var3);
            printf("%06X ", bob.var4);
    
        } // if
    
        else {
            printf("Incorrect!\n");
        } // else
    } // process_packet

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Most likely, yes, it's padding. But we can't tell you how to solve it because it's different for each compiler. You'll have to tell us what compiler you use first.
    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
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    If you change:
    Code:
    if (sizeof(data) == 8) {
    into
    Code:
    if (sizeof(bob) == 8) {
    Then your output will be "Incorrect!".

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 12-03-2008, 03:10 AM
  2. Fixing my program
    By Mcwaffle in forum C Programming
    Replies: 5
    Last Post: 11-05-2008, 03:55 AM
  3. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  4. Array of struct pointers - Losing my mind
    By drucillica in forum C Programming
    Replies: 5
    Last Post: 11-12-2005, 11:50 PM
  5. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM