Я определил две переменные:
uint8_t a[2];
uint16_t b;
Далее я хочу использовать в a
качестве переменной типа uint16_t
, например
b = (uint16_t)a;
Но это неправильно! Мои программы не работают правильно с таким кодом. Все в порядке , когда я заменить b
на uint8_t b[2]
и операции использования поэлементные.
Почему?
Ответы:
a
указатель на массив байтов Если вы приведете его к uint16_t и назначите егоb
, тогда онb
будет содержать адрес базы массива (где он хранится) в SRAM. Если вы хотите рассматривать два байта массиваa
как целое число, используйте объединение, как предложено пользователем 14284, но имейте в виду, что объединение будет представлять байтовый массив в порядке байтов памяти в архитектуре (в AVR это будет мало -endian, что означает, что байт 0 является наименее значимым байтом). Способ написать это в коде:Другой способ сделать это без использования объединения - привести
a
к указателю uint16_t, а затем разыменовать его следующим образом:Если вы используете буфер для хранения данных с прямым порядком байтов (например, порядок байтов в сети), то вам нужно будет поменять местами, чтобы использовать любой из этих методов. Способ сделать это без каких-либо ветвей или временных переменных:
Между прочим, это не AVR или даже встроенная проблема. Прикладной уровень сетевого код написан для ПК , как правило , вызовов функций , называемых
htonl
,htons
(хоста к сети, 32- и 16-разрядные варианты) иntohl
,ntohs
(сеть к хосту, 32- и 16-разрядные варианты) , чьи реализации целевые зависят от архитектуры , как ли они поменять местами байты или нет (при условии, что байты, передаваемые «по проводам», всегда имеют порядковый номер, если они являются частью многобайтовых слов).источник
a
» сам по себе является указателем.-fno-strict-aliasing
.Если вы хотите объединить две 8-битные переменные в 16-битную переменную, используйте a
union
. Если вы хотите привести единственный членa
вb
, укажите, какой элемент массива вы хотите использовать.источник
На ваш код вы приводите только указатель на массив.
Вам нужно привести значение, на которое указывает
a
.Я никогда не использовал AVR, но если вы работаете с 16-битной архитектурой, вы должны убедиться, что слово выровнено. Невыполнение этого требования может привести к исключению.
источник
Каждый член представляет собой 8-битное число. Он не может вместить ничего большего. Приведение его к 16-битам ничего не делает для a . Он просто извлекает любое значение, которое может содержать a , и преобразует его в 16 бит, чтобы оно соответствовало формату b, когда значение сохраняется там.
Вы даже не относятся к члену . Вы должны использовать [0] или [1] (а не [2]!). Если вы используете сам по себе, вы только получите адрес этого. (Хороший улов, Бруно).
Объявление быть массивом из двух 8-битных чисел не делает его 16-битовое число, либо. Вы можете делать некоторые вещи программно для хранения и извлечения 16-битных значений, используя 8-битные последовательности, но не так, как вы думали.
источник
Если вы хотите преобразовать байты в
a
16-битное значение, а представление имеет младший порядок (младшие 8 битов значения входят в первый байт), выполнитеДля представления с прямым порядком байтов
Избегайте использования приведения или объединения указателей для этого, так как это приводит к проблемам переносимости.
источник