2015-03-20 3 views
1

Доброе утро, я пытаюсь создать структуру данных, которая может использоваться в разных приложениях, но передана функции передачи в том же виде, Я использую netbeans на данный момент, но это будет передано дальше к dsPIC30F (16-бит),C Вложенные союзы и структуры

typedef union { 

    union { 

     struct { 
      unsigned bit0 : 1; 
      unsigned bit1 : 1; 
      unsigned bit2 : 1; 
      unsigned bit3 : 1; 
      unsigned bit4 : 1; 
      unsigned bit5 : 1; 
      unsigned bit6 : 1; 
      unsigned bit7 : 1; 

      unsigned bit8 : 1; 
      unsigned bit9 : 1; 
      unsigned bit10 : 1; 
      unsigned bit11 : 1; 

      union { 

       struct { 
        unsigned bit12 : 1; 
        unsigned bit13 : 1; 
        unsigned bit14 : 1; 
        unsigned bit15 : 1; 
       }; 
       unsigned char value; 
      } lastfour; 

     }; 
     unsigned int value : 16; 
    }; 

    union { 

     struct { 

      union { 

       struct { 
        unsigned bit0 : 1; 
        unsigned bit1 : 1; 
        unsigned bit2 : 1; 
        unsigned bit3 : 1; 
       }; 
       unsigned char value; 
      } firstfour; 

      unsigned bit4 : 1; 
      unsigned bit5 : 1; 
      unsigned bit6 : 1; 
      unsigned bit7 : 1; 

      unsigned bit8 : 1; 
      unsigned bit9 : 1; 
      unsigned bit10 : 1; 
      unsigned bit11 : 1; 
      unsigned bit12 : 1; 
      unsigned bit13 : 1; 
      unsigned bit14 : 1; 
      unsigned bit15 : 1; 


     }; 
     unsigned int value : 16; 
    }; 

} foo; 

затем я использую следующий код для проверки работоспособности.

int main(int argc, char** argv) { 

    foo a; 
    a.value =0; 
    a.lastfour.value = 0xF; 

    printf("%d", a.value); 

    return (EXIT_SUCCESS); 
} 

Напечатанное значение 0, однако из-за союз я нахожусь под впечатлением две структур разделяют ту же память (16 бит), поэтому после установки «lastfour» на «значения» 0xf должна теперь быть 0xF000.

Может кто-нибудь дать некоторые указания на то, что я делаю не так и почему «значение» не читает ту же область памяти, которая содержит «» lastfour

+0

Вам нужна дополнительная помощь? Если нет, пожалуйста, проверьте один из ответов ниже. Благодаря! –

ответ

1

Во-первых, я удивлен, что это даже компилируется для вас. У вас есть два анонимных unions в вашем foo типах, и у них есть повторяющиеся имена участников (bit4, bit5 и т. Д.). Ваш код не компилировался для меня. Вы должны указать имена для двух unions или переименовать bits, чтобы они не конфликтуют.

Во-вторых, ваши союзы firstfour и lastfour, скорее всего, будут иметь 8 бит, а не 4, так как минимальный размер char составляет 8 бит. Это собирается сбросить все ваши другие бит.

В-третьих, ваши союзы firstfour и lastfour не начинаются с бит 12 в памяти. Они будут выровнены по мере необходимости для вашего процессора, вероятно, на следующем 2-байтовом или 4-байтовом смещении. Попробуйте распечатать sizeof(foo) в вашей функции. Я гарантирую, что вы увидите что-то вроде 4 или 8, а не 2, как вы ожидаете.

В-четвертых, этот больший размер является причиной того, что вы видите значение «0», напечатанное в тестовом коде. Первые 16 бит равны нулю. Установленный вами 0xF находится либо в следующих 16 битах, либо, возможно, в следующих 32 битах, в зависимости от того, как ваш компилятор выравнивает объекты.

Вот структура структуры, которая должна работать для того, что вы пытаетесь сделать. Я тестировал его, и он работает для меня. Упаковывает все в 2 байта.

typedef struct { 
    union { 
     struct { 
      uint16_t firstfour : 4; 
      uint16_t secondfour : 4; 
      uint16_t thirdfour : 4; 
      uint16_t lastfour : 4; 
     }; 
     /* EDIT - Duplicate structure with different member names 
      added, in response to a comment below. */ 
     struct { 
      uint16_t nibble1 : 4; 
      uint16_t nibble2 : 4; 
      uint16_t nibble3 : 4; 
      uint16_t nibble4 : 4; 
     }; 
     struct { 
      uint16_t bit0 : 1; 
      uint16_t bit1 : 1; 
      uint16_t bit2 : 1; 
      uint16_t bit3 : 1; 
      uint16_t bit4 : 1; 
      uint16_t bit5 : 1; 
      uint16_t bit6 : 1; 
      uint16_t bit7 : 1; 
      uint16_t bit8 : 1; 
      uint16_t bit9 : 1; 
      uint16_t bit10 : 1; 
      uint16_t bit11 : 1; 
      uint16_t bit12 : 1; 
      uint16_t bit13 : 1; 
      uint16_t bit14 : 1; 
      uint16_t bit15 : 1; 
     }; 
     uint16_t value; 
    }; 
} foo; 
+0

Спасибо, некоторые действительно полезные вещи там, однако Если бы у меня были разные объявления для firstfour secondfour ... и т. Д. (Например, nibble1 nibble2 ...), которые я все еще хотел получить в одном и том же пространстве памяти –

+0

Не совсем уверен, что вы просите, но если вы имеете в виду, что хотите получить доступ к «firstfour» с именем «nibble1», вы можете добавить еще одну структуру в объединение и использовать эти имена. В основном копировать-вставить первую структуру и переименовать поля. –

+0

Отредактировал мой ответ, чтобы добавить структуру nibble *, о которой я думаю, что вы просите. –

1

Оно определяется реализацией (зависит от размера int -s, то процессор, endianness, ABI и т. д.). Разумеется, на Android-планшете с процессором ARM и на рабочем столе x86-64 он будет отличаться от 64-битного достоинства Linux (дистрибутива).

Я считаю, что вам следует избегать union -s с битполями в struct, если вы не думаете о конкретной реализации.

Я не уверен, что ваш код позволяет вызвать произвольную функцию (в частности, потому, что указатели могут иметь различные размеры, чем int -s, вы можете захотеть использовать intptr_t), но это не имеет много общего с вашим кодом ,

Если вы хотите, чтобы иметь возможность вызвать произвольную функцию произвольной подписи, рассмотрите возможность использования некоторой библиотеки, например, libFFI (что, конечно же, специфично для реализации).

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

Кстати, ваш код является неправильным, так как lastfour содержит char (как правило, 8-бит байта), поэтому он не может занять такое же место, как 4-бит битовое поле (bits12 ... bits15); может быть, вы должны заменить unsigned char value; в вашем firstfour с unsigned valfourbits : 4; и т.д ...

Чтобы передать некоторые динамически типизированных данных для некоторой функции, вы можете иметь некоторые tagged union. Glib GVariant type - пример реального мира (и вы можете погрузиться в исходный код).

Если вы знаете немного ассемблера, вы можете попытаться просмотреть код ассемблера, сгенерированный вашим компилятором.Если компиляция с GCC, попробуйте скомпилировать программу с помощью gcc -Wall -fverbose-asm -O -S your-main.c затем посмотреть (с помощью редактора или пейджера) в сгенерированный код ассемблера в your-main.s

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

Общее правило правило - избегать битполей. У этого правила есть исключения, но вы должны сначала узнать намного больше о C.

+0

Извините, что я забыл добавить это, это для 16-битного ПОС, поскольку я понимаю, что ': 4' определяет длину символа. По существу у меня есть функция (dataPacket * a) { {a.value); } , но я хочу заполнить пакет различными значениями, используемыми в разных кусках бит. –

+0

Почти каждый 16-разрядный микроконтроллер, с которым я столкнулся в этом столетии, «char» является 8-битным байтом (я никогда не слышал о 4 бит 'char'-s). И, пожалуйста, отредактируйте свой вопрос, чтобы улучшить его! –

+0

Я нашел [this] (http://stackoverflow.com/questions/3305933/use-of-the-operator-in-c), чтобы объяснить 4-битный символ –

Смежные вопросы