Как преобразовать 4 байта в беззнаковую длинную переменную?

Как правильно преобразовать 4 байта в одну беззнаковую длинную переменную?

Я программирую PIC18 на MPLAB C18, и это мой код.

unsigned long theseconds = 0x00;
BYTE timeToSave[4];

timeToSave[0] = 0xFF;
timeToSave[1] = 0xFF;
timeToSave[2] = 0x01;
timeToSave[3] = 0x01;

theseconds  =   timeToSave[0] & 0xFF;
theseconds |=  (timeToSave[1] << 8) & 0xFFFF;
theseconds |=  (timeToSave[2] << 16) & 0xFFFFFF;
theseconds |=  (timeToSave[3] << 24) & 0xFFFFFFFF;
printf("\r\nSeconds:%lu",theseconds);

Вот результат, который я продолжаю получать: Секунды: 255.

Спасибо!


person Ammar    schedule 15.07.2013    source источник
comment
Только не берите маски, они вам не нужны. Остальное кажется нормальным, если буфер, который вы читаете, имеет обратный порядок байтов.   -  person everclear    schedule 15.07.2013
comment
@everclear Если все в порядке, зависит от размера int. Это работает, только если sizeof(int)==sizeof(long)   -  person jeb    schedule 15.07.2013
comment
@jeb да, видел, только что вернулся с сайта с картинками ;-)   -  person everclear    schedule 15.07.2013
comment
@everclear Я ценю усилия   -  person Ammar    schedule 15.07.2013


Ответы (1)


Это должно работать

unsigned long theseconds = 0x00;
BYTE timeToSave[4];

timeToSave[0] = 0xFF;
timeToSave[1] = 0xFF;
timeToSave[2] = 0x01;
timeToSave[3] = 0x01;

theseconds  =   timeToSave[3];
theseconds  <<= 8;
theseconds  |=   timeToSave[2];
theseconds  <<= 8;
theseconds  |=   timeToSave[1];
theseconds  <<= 8;
theseconds  |=   timeToSave[0];
printf("\r\nSeconds:%lu",theseconds);

Ваш код не работает по двум причинам.
Я предполагаю, что int является 16-битным, поэтому сдвиг 16 или 24 приведет к 0, так как правило в ANSI-C гласит, что BYTE из timeToSave[x] (на самом деле беззнаковый символ) должен быть расширена до int.
Очевидно, что сдвиг 16-битного значения более 15 раз также приведет к 0.

Но почему вы получаете 255, а не 65535?
Я полагаю, что компилятор не совместим с ANSI и не будет правильно расширять ваш беззнаковый символ.

Чтобы ваш код работал, должно быть достаточно привести каждую строку.

theseconds  =   timeToSave[0];
theseconds |=  ((unsigned long)timeToSave[1] << 8);
theseconds |=  ((unsigned long)timeToSave[2] << 16);
theseconds |=  ((unsigned long)timeToSave[3] << 24);

Маска & не имеет смысла, так как значение не может быть за пределами диапазона

person jeb    schedule 15.07.2013
comment
Он по-прежнему выдает 255 в качестве результата. - person Ammar; 15.07.2013
comment
Извините, я забыл символ | перед знаком равенства - person jeb; 15.07.2013
comment
@jeb по умолчанию MPLAB C18 не выполняет продвижение целых чисел - person ouah; 15.07.2013
comment
@ouah И именно поэтому он не соответствует ANSI - person jeb; 15.07.2013
comment
Параметр @jeb -Oi должен быть включен на C18, чтобы иметь поведение, совместимое с ANSI в отношении целочисленных акций. - person ouah; 15.07.2013