LINUX.ORG.RU

[C] доступ к байту внутри int32

 


0

1

Вот такой код прекрасно компилится (что естественно)

  int32 a = 0xDEADBEEF;
  unsigned char *pa8 = (unsigned char*)(&a);
  printf( "%X %X\n", *(pa8+1), *(pa8+2) );
и выдает на х86 ожидаемый результат:
BE AD
А что будет, если целевая машина не-х86, и на ней нельзя обращаться к невыровненным на слово данным? Вылетит в trap? Ведь здесь мы читаем память из середины машинного слова. Или компилятор как-нибудь разберется?


sparc:

bash# ./a.out
AD BE

ttnl ★★★★★
()

Одиночный байт на таких машинах можно читать из любого места afaik. Дело в выравнии по размеру данных, а один байт всегда выровнен.

unC0Rr ★★★★★
()

Выравниванием займется конпелятор, а вот с порядком байтов придется трахаться господину разработчику.
Алсо, твой способ !Ъ, юзай >> &&.

anonymous
()

Хм, так ни разу не делал. Но почему бы не использовать простой сдвиг?

printf("%X %X\n", (a >> 24) & 0xFF, (a >> 16) & 0xFF);

UVV ★★★★★
()
Ответ на: комментарий от anonymous

Как вариант, делать hton[ls]. Сетевой порядок всегда один и тот же.

anonymous
()
Ответ на: комментарий от UVV

Я привел этот код просто как простой пример, причем похоже пример не совсем корректный. На самом деле я хочу написать функцию, которая накладывает битовую маску произвольной длины на массив с произвольным смещением от начала. Т.е. что-то вроде

void apply_mask( void *dst, uint offset, const void *mask, uint num )

где dst -первый байт куска памяти, на который надо наложить маску
offset - бит, с которого начинать накладывать
mask - маска
num - количество бит в маске
Внутри я буду работать, естественно, т.ч. с байтами. И вот меня интересует, не вылетит ли в этом случае. Отличие от моего примера в том, что конпелятор тут не может знать, что лежит в dst, поэтому не сможет применить свои грязные трюки, если они нужны.

gaga
() автор топика
Ответ на: комментарий от gaga

Если будешь использовать битовые операции над одинаковыми типами данных и разберешься с порядком байтов (man gcc builtin macros), то всё будет заебок.

anonymous
()

Или компилятор как-нибудь разберется?

Тип char представляет объект минимального размера (но не менее 8 бит), к которому можно обрщаться напрямую.

А что будет, если целевая машина не-х86, и на ней нельзя обращаться к невыровненным на слово данным?

Значит у типа char будет размер слова, только и всего.

LamerOk ★★★★★
()

А что будет, если целевая машина не-х86, и на ней нельзя
обращаться к невыровненным на слово данным? Вылетит в trap?
Ведь здесь мы читаем память из середины машинного слова.
Или компилятор как-нибудь разберется?

Компилятор С сгенерит чтение выровненного слова и выделение одного char из него. Иначе бы код char foo[4]; foo[3] = foo[2]; не работал.

sf ★★★
()
Ответ на: комментарий от sf

Спасибо, я так и понял уже после того, как написал пост). Для преобразованного из void* указателя ситуация, как я понимаю, аналогичная?

gaga
() автор топика
Ответ на: комментарий от sf

А и еще. Справедливо ли то же самое для uint8? На всех ли машинах можно обратиться к отдельному байту через указатель?

gaga
() автор топика
Ответ на: комментарий от gaga

А и еще. Справедливо ли то же самое для uint8?
На всех ли машинах можно обратиться к отдельному байту через указатель?

Да, если uint8(_t) определен в <stdint.h> (CHAR_BITS == 8).

sf ★★★
()

А что будет, если целевая машина не-х86, и на ней нельзя обращаться к невыровненным на слово данным?

Есть понятие «естественное выравнивание» - это выравнивания по размеру типа.

Если поинтер на данные удовлетворяет естественному выравниванию - значит проблем не будет. Иначе - изволь пользовать memcpy.

Rzhepish
()
Ответ на: комментарий от Rzhepish

Да, это понятно, вопрос не об этом. По сути я его неправильно сформулировал. Правильно так: на любой ли машине можно обратиться к отдельному байту по указателю и имеет ли при этом значение, на что этот указатель изначально ссылался?

gaga
() автор топика
Ответ на: комментарий от gaga

> Да, если uint8(_t) определен в <stdint.h> (CHAR_BITS == 8).

А если нет ? :3

Если нужен доступ к потоку битов - придется по char-ам вычитывать, битовыми операциями производить преобразования и записывать обратно.

Многие портабельные архиваторы вынуждены это делать.

Думаю, на такой архитектуре отсутствие доступа к 8-битным байтам будет не не самой большой проблемой.

sf ★★★
()
Ответ на: комментарий от sf

Ну к битам на любой машине только битовыми операциями можно доступ получить. Меня интересуют байты. Завтра попробую на tms,там char как раз 32 бита. Хотя я уже понял, что можно забить и считать, что на практике байт доступен

gaga
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.