简体   繁体   中英

Storing a uint64_t data type in a char type field present in a union in C

Hi I have the following union which is part of a larger struct and I want to store a uint64_t (64 bits size) data in this union. However i want to store it by accessing the id_data field since the others are not large enough for a complete uint64_t. But i dont know how to assign my uint64_t data into this id_data field.

I know how to read the uint64_t data from this field.But somehow dont know how to assign values to it.

Any help will be appreciated.

Thanks.

union {
    struct id_ts {          /* ICMP Timestamp */
        uint32_t otime; /* Originate */
        uint32_t rtime; /* Receive */
        uint32_t ttime; /* Transmit */
    } id_ts;
    struct id_ip  {
        struct xyz_abc idi_ip;
        /* options and then 64 bits of data */
    } id_ip;
    struct ra_addr id_radv;
    uint32_t id_mask;
    char    id_data[1];
} icmp_nnn;

You could use memcpy :

uint64_t val;
memcpy((void*)&icmp_nnn.id_data[0], (void*)&val, sizeof(val));

You aren't really assigning it to the id_data member. Just memcpy into the memory space used by the union. id_data[0] will correspond to the start of the union .

Err... why not just make a uint64_t member of the union you can assign to?

As written, you can't write it into the id_data field because that field is only one byte long. Using more space than that (I believe) is implementation defined.

That said, pretty much anything you do with a union is implementation defined anyway, so if you want the nasty nasty gross insane platform dependent way to do it, you use bit shifting to get the desired effect. Note that you may need to change

size_t idx = 0;
uint64_t myData = /* ... */;
union icmp_nnn structure;
for (; idx < 8; ++idx)
{
    // For big endian machines
    structure.id_data[idx] = (myData >> 8*idx) & 0xFF;
    // For little endian machines
    structure.id_data[7-idx] = (myData >> 8*idx) & 0xFF;
}

Billy3

如果您不能更改union声明,则memcpy应该仍然允许您执行所需的操作。

Is there a reason why you can't declare a uInt64_t member of the union?

You say you know how to read the uint64_t data from the id_data field? How are you doing that exactly? The get should not be much different to the set?

To read from the field:

uint64_t ui = *(uint64_t*)icmp_nnn.id_data;

To write to the field;

*(uint64_t*)icmp_nnn.id_data = 12345;

But really you should just add a uint64_t member to the union if it is your own code (ie not a library).

You should use memcpy() , but there's really no reason to use the id_data field as the destination - just use the entire union itself, which more clearly expresses your intent.

uint64_t src;
memcpy(&icmp_nnn, &src, sizeof src);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM