Как да конвертирате 4 byes в неподписана дълга променлива?

Как правилно конвертирате 4 byes в една дълга променлива без знак?

Програмирам 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 и няма да разшири вашия неподписан char по подходящ начин.

За да работи кодът ви, трябва да е достатъчно да прехвърляте всеки ред.

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