Программирование на C - указатель адреса байтового разделения - PullRequest
0 голосов
/ 24 апреля 2018

У меня есть следующая переменная var, которая является 32-битным значением без знака. Я работаю над системой с прямым порядком байтов.

unsigned long var = 1;
// Representation: 00000000 00000000 00000000 00000001

Теперь я хочу получить доступ к первому и последнему 16 битам через:

(((unsigned short*)&var)[0])) => 00000000 00000001

(((unsigned short*)&var)[1])) => 00000000 00000000

Есть ли какая-либо документация C для этого типа разделения адреса указателя? Я получил это работает, но я не знаю, как это работает.

Спасибо

1 Ответ

0 голосов
/ 24 апреля 2018

Как правило, вы можете получить доступ к любому типу данных в C с помощью указателя на тип символа, например unsigned char* или uint8_t*.Если вы приведете var к такому символьному указателю, вы получите указатель на первый байт:

unsigned char* cptr = (unsigned char*)&var;

Затем вы можете ссылаться на этот указатель для получения содержимого, выполнив *cptr или cptr[0] - это означает то же самое.В системе с прямым порядком байтов теперь у вас есть указатель на младший байт.cptr[1] выдаст байт после этого и т. Д.

Однако это только гарантированно работает для типов символов!Никакой другой тип, такой как unsigned short, не может быть использован - это дало бы так называемое «строгое нарушение алиасинга». Что такое строгое правило псевдонимов? Это означает, что если у вас есть такой код:

unsigned long var = 1;
*(unsigned short*)&var = 123;
if(var == 1)
  printf("Look mom, I violated strict aliasing!");

Тогда компилятор может генерировать код, который выполняет оператор printf.Или он также может изменить var, как вы ожидаете, и не выполнять printf.Или он может рухнуть и сгореть: это неопределенное поведение, может произойти все что угодно.Подобные ошибки часто появляются, в частности, в компиляторе gcc с высокой оптимизацией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...