Хранение типа данных uint64_t в поле типа char, присутствующего в объединении в C - PullRequest
1 голос
/ 09 июля 2010

Привет У меня есть следующее объединение, которое является частью большей структуры, и я хочу сохранить данные uint64_t (размер 64 бита) в этом объединении.Однако я хочу сохранить его, открыв поле id_data, так как остальные недостаточно велики для полного uint64_t.Но я не знаю, как назначить мои данные uint64_t в это поле id_data.

Я знаю, как читать данные uint64_t из этого поля. Но как-то не знаю, как присвоить ему значения.

Любая помощь будет оценена.1007 *

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;

Ответы [ 6 ]

1 голос
/ 09 июля 2010

Вы можете использовать memcpy:

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

Вы не назначаете его члену id_data. Просто memcpy в пространство памяти, используемое объединением. id_data[0] будет соответствовать start из union.

0 голосов
/ 09 июля 2010

Вы должны использовать memcpy(), но на самом деле нет смысла использовать поле id_data в качестве пункта назначения - просто используйте весь сам союз, который более четко выражает ваше намерение.

uint64_t src;
memcpy(&icmp_nnn, &src, sizeof src);
0 голосов
/ 09 июля 2010

Для чтения из поля:

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

Для записи в поле;

*(uint64_t*)icmp_nnn.id_data = 12345;

Но на самом деле вы должны просто добавить член uint64_t в объединение, если оно вашекод (т.е. не библиотека).

0 голосов
/ 09 июля 2010

Есть ли причина, по которой вы не можете объявить член союза uInt64_t?

Вы говорите, что знаете, как читать данные uint64_t из поля id_data? Как ты это делаешь? Гет не должен сильно отличаться от набора?

0 голосов
/ 09 июля 2010

Если вы не можете изменить объявление union, memcpy все равно должно позволять вам делать то, что вы хотите.

0 голосов
/ 09 июля 2010

Ошибка ... почему бы просто не сделать член союза uint64_t, который вы можете назначить?

Как написано, вы не можете записать его в поле id_data, потому что это поле имеет длину только один байт. Использование большего пространства, чем это (я считаю) определяется реализацией.

Тем не менее, почти все, что вы делаете с объединением, в любом случае определяется реализацией, поэтому, если вы хотите сделать противный, противный безумной платформе зависимый способ сделать это, вы используете сдвиг битов, чтобы получить желаемый эффект. Обратите внимание, что вам может потребоваться изменить

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

...