Тип casting char указатель на целочисленный указатель

Итак, я увидел несколько примеров того, как можно было узнать, какая архитектура может быть найдена. Пусть говорят, что у нас есть целочисленный указатель, который указывает на тип данных int. И пусть говорят, что значение int равно 0x010A0B12. В архитектуре с небольшим количеством символов наименее значимый байт, т.е. 12, будет сохранен в наименьшем адресе памяти, правильно? Таким образом, младший байт в 4-байтовом целой будет 12.

Теперь, на проверку. Если мы объявляем указатель char p и набираем целочисленный указатель на char * и сохраняем его в p и печатаем разыменованное значение p, мы получим ключ к контенту архитектуры. Если это 12, мы немного судим; 01 означает большой эндиан. Это звучит очень аккуратно...

int a = 0x010A0B12;
int *i = &a;
char *p = (char*)i; 
printf("%d",*p); // prints the decimal equivalent of 12h!

Несколько вопросов здесь, действительно. Поскольку указатели строго типизированы, не должен ли указатель символа строго указывать на тип данных char? И что с печатью с% d? Разве мы не должны печатать с% c, для символа?

Ответы

Ответ 1

Поскольку указатели строго типизированы, не должен ли указатель символа строго указывать на тип данных char?

C имеет правило, что любой указатель можно безопасно преобразовать в char* и void*. Таким образом, преобразование int* в char* разрешено, и оно также переносимо. Указатель будет указывать на начальный байт вашего внутреннего представления int.

Не следует ли печатать с %c, для символа?

Другое дело в игре здесь: список аргументов переменной длины printf. Когда вы передаете char в нетипизированный параметр printf, применяется преобразование по умолчанию: char преобразуется в int. Вот почему формат %d делает число просто прекрасным и печатает его, как вы ожидаете.

Вы также можете использовать %c. Код, обрабатывающий спецификатор %c, считывает аргумент как int, а затем преобразует его в char. 0x12 - особый символ, поэтому вы не увидите для него равномерной распечатки.

Ответ 2

Поскольку указатели строго типизированы, не должен ли указатель символа строго указывать на тип данных char?

Это своего рода поведение undefined - но такое, что большинство разумных реализаций будут делать то, что вы имеете в виду. Таким образом, большинство людей будет говорить об этом хорошо.

И что с печатью с% d?

Формат% d ожидает аргумент типа int, а фактический arg типа char присваивается int с помощью обычных правил C. Так что все в порядке. Вероятно, вы не хотите использовать% c, поскольку содержимое байта, на которое указывает p, может быть любым байтом, а не всегда действительным текстовым символом.