Тип 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, может быть любым байтом, а не всегда действительным текстовым символом.