Битовые операции и uint64_t

RxMaxx
Offline
Зарегистрирован: 10.04.2020

Добрый день.

Допустим у меня есть число размером 8 байт:

uint64_t dat=8681104427521506943;

(что есть 01111000 01111001 01111010 01111011 01111100 01111101 01111110 01111111)

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

byte D; 
for (int i = 0; i < 8; i++)  D = (dat & (255 << (8 * i))) >> (8 * i);
Для i=0 и 1 все работает нормально, но для i=2 и более у меня получаются нули. Допустим для i=3 пытаемся вычислить: D = (dat & (255 << 24)) >> 24; - будет ноль, но если считать уже "вручную" D=(dat&42781900804278190080)>>24; - то получаем верное значение 01111100.
Как так? Ардуино не умеет верно работать с большими числами и не может сделать сдвиг 255 << 24?
rkit
Offline
Зарегистрирован: 23.11.2016

dat & (255 << (8 * i)

Эта часть не нужна.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

RxMaxx, можно сделать проще и красивее - просто читать "dat" с нужным сдвигом, и всё:

for (int i = 0; i < 8; i++) { Serial.println (  *(((uint8_t*)&dat)+i), HEX); }

 

RxMaxx
Offline
Зарегистрирован: 10.04.2020

Спасибо, оба способа рабочие, но при условии, что я использую переменную в 1 байт. А если нет? Если мне просто нужно будет применить маску вида 255 << (8 * i)? Почему это не работает?

rkit
Offline
Зарегистрирован: 23.11.2016

RxMaxx пишет:

Спасибо, оба способа рабочие, но при условии, что я использую переменную в 1 байт. А если нет? Если мне просто нужно будет применить маску вида 255 << (8 * i)? Почему это не работает?

Тип этого выражения по умолчанию int, 16 бит. Нужно указывать явно static_cast<uint64_t>(255) << (8 * i)

RxMaxx
Offline
Зарегистрирован: 10.04.2020

Точно! Надо же было само 255 расширить до uint64_t, а я пытался так писать (uint64_t)(255 << (8 * i)), все теперь разобрался, спасибо! 

nik182
Offline
Зарегистрирован: 04.05.2015

А что будет если так? (uint64_t)(255Lu << (8 * i))

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

В том и дело, что в Си L это long, a uint64_t это long long. Не пайдеть. 

А LL GCC как микрософт не понимает.

RxMaxx
Offline
Зарегистрирован: 10.04.2020

nik182 пишет:

А что будет если так? (uint64_t)(255Lu << (8 * i))

4 из 8

RxMaxx
Offline
Зарегистрирован: 10.04.2020

(255LL << (8 * i)) - а вот так все 8 из 8

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну, значит, понимаеть :-)

RxMaxx
Offline
Зарегистрирован: 10.04.2020

Еще небольшой вопрос. С точки зрения стандартного ардуиноского компилятора числа записанные как

uint64_t dat=8681104427521506943 и как

uint64_t dat=120LLu<<56|121LLu<<48|122LLu<<40|123LLu<<36|124LLu<<24|125LLu<<16|126LLu<<8|127LLu

выглядят одинаково? Т.е. компилятор сразу делает подобные вычисления на стадии компиляции, или они будут производиться потом силами МК?