2010-08-07 2 views
4

C++ У меня есть следующая структура:битого сдвиг в

struct SysData 
{ 
     // Topic (32 bits) 
     UTL_UINT16_Tdef SystemID:11; // set to decimal 25 
     UTL_UINT16_Tdef TypeID:5;  // set to 2 (telemetry type) 
     UTL_UINT16_Tdef ContentID;  // set to decimal 1234 
} 

SysData MsgHdr; 
MsgHdr.SystemID = 25; 
MsgHdr.TypeID  = 2; 
MsgHdr.ContentID = 0; 

Если я что-то вроде этого:

unsigned int a; 
    memcpy(&a, &MsgHdr, sizeof(MsgHdr)); 
    headerInfo[0] = a & 0x7FF; 
    headerInfo[1] = (a >> 16) & 31; 
    headerInfo[2] = (a >> 21) & 0xFFFF; 

headerInfo [0] должны иметь значение 25, но она имеет 36. Что я делаю неправильно?

+0

Что такое тип 'headerInfo'? – mjschultz

+0

@mjschultz headerInfo - это массив unsigned int – Blade3

+0

Почему вы так делаете ... если бы «союз» не подходит? – t0mm13b

ответ

3

Вы не должны догадываться о внутреннем представлении SysData.Compiler может выбрать объединение полей бит или нет, чтобы выровнять их влево или вправо и т. Д. Он может даже выбрать сопоставление их с 32-битным целым числом для выполнения задач , Вы просто не можете знать. Неиспользованная часть битполя может содержать мусор, и, вероятно, там, где вы получили 36.

Странно, но не очень сложно проверить. Измените свои 25 на другие значения и посмотрите, что вы получите.

Однако memcopying вашей структуры для некоторых неподписанных int, вероятно, не очень хорошая идея. Почему бы вам не получить доступ к битовому полю напрямую? Как и в headerInfo[0] = MsgHdr.SystemID;, для этого нужны битподы. В вашем примере memcopy - это просто потеря времени (а также опасная, как вы можете видеть).

0

Реализация битполей не определена и зависит от того, какой компилятор вы используете.

(EDIT: игнорировать мое неправильное предположение о том, где 36 исходит из)

Я не могу думать о том, как вы получите до 36, но с битовыми полями, я настоятельно рекомендовал бы читать их, используя обычный доступ для чтения вместо того, чтобы их перемещать, то есть

SysData *pSysData = (SysData *) &MsgHdr; 
headerInfo[0] = pSysData->ContentID; 

КВт, я не понимаю ваш пример. Вы говорите, что headerInfo [0] должно быть 25. Но не должно быть 0? В вашем примере указано, что ContentID равно 0, и я понял, что вы пытаетесь его прочитать.

+0

«Должно быть нулевым», если принять соответствующую конкретизацию. – Jamie

+1

100010 - 34, а не 36. – Troubadour

+0

Нет, «должно быть равным нулю», что означает, что он явно указал ContentID = 0 в примере, и учитывая, что вторая часть кода AND имеет результат с 0x7ff, похоже, что он собирается для ContentID. – EboMike

0

За исключением возможных проблем со стороны или проблем с упаковкой, не должен сдвиг на headerInfo [1] равным 11, а headerInfo [2] - 16?

0

Как EboMike, не может понять, где вы получаете 36

а) десятичное 25 = 00000011001 б) десятичных 2 = 00010 с) десятичными 1234 = 000010011010010

Так различные комбинации :

  • аЬс = 0000001 [100100] 010000010011010010
  • ACB = 0000001 [100100] 00100110 [100100] 0010
  • BAC = 000100000001 [100100] 0010011010010
  • BCA = 0001000001001101001000000011001
  • кабина = 0000100110 [100100] 000001 [100100] 010
  • сЬа = 0000100110 [100100] 001000000011001

Ничто не заканчивается в требуется последовательность 100100 бит, поэтому, если структура фактически не хранится над двумя uint или что-то неловкое происходит, я теряюсь. Загрузите в отладчик и посмотрите, что на самом деле хранит.

0

Если я это сделать:

#include <stdio.h> 
#include <memory.h> 

typedef unsigned short UTL_UINT16_Tdef; 

struct SysData { 
    // Topic (32 bits) 
    UTL_UINT16_Tdef SystemID:11; // set to decimal 25 
    UTL_UINT16_Tdef TypeID:5;  // set to 2 (telemetry type) 
    UTL_UINT16_Tdef ContentID;  // set to decimal 1234 
}; 

int main() { 

    SysData MsgHdr; 

    MsgHdr.SystemID = 33; 
    MsgHdr.TypeID  = 22; 
    MsgHdr.ContentID = 11; 

    unsigned int a; 
    memcpy(&a, &MsgHdr, sizeof(MsgHdr)); 

/* 
    headerInfo[0] = a & 0x7FF; 
    headerInfo[1] = (a >> 16) & 31; 
    headerInfo[2] = (a >> 21) & 0xFFFF; 
*/ 

    printf("%08X %i\n", a, sizeof(SysData)); 

    printf("0: %i\n", a & 0x7FF); 
    printf("1: %i\n", (a >> 11) & 31); 
    printf("2: %i\n", (a >> 16) & 0xFFFF); 

} 

Я получаю ожидаемые результаты, и codepad делает тоже - http://codepad.org/XNm0Yp90

+0

с каким компилятором и какие варианты компиляции? – kriss

+1

Зависит от компилятора. Реализация битового поля не определена, поэтому попытка извлечь данные из них напрямую - это русскую рулетку. – EboMike

+0

gcc/msc/intelc на x86, но дело в том, чтобы проверить, не работает ли моя версия для OP, или она делает, и он сделал что-то не так в другом месте. У нас нет полного источника здесь или даже определений типов. – Shelwien

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