Во-первых, переменная b
объявлена с типом char *
. Вы пытаетесь инициализировать его значением &a
типа int *
. Это незаконно. Код недействителен C. Поведение не определено.
Во-вторых, если ваш компилятор сумел пропустить эту инициализацию, то, вероятно, он выполнил неявное преобразование значения int *
в char *
. Это делает указатель b
указывать только на один байт переменной a
. Значение этого единственного байта - это то, что вы видите через *b
. Какой из байтов (в терминах исходного значения a
) определяется реализацией. Например. вы обычно получаете младший байт (0xEF
) или старший байт (0xAB
).
В-третьих, это определение реализации, независимо от того, подписан или нет знак char
. Это означает, что значение *b
может быть подписано или без знака в зависимости от вашей реализации. Когда вы передаете char
значение *b
на вариационную функцию printf
, то значение char
значение автоматически преобразуется в int
. Результат этого преобразования, как правило, зависит от подписи типа char
. Если ваш b
указывает на байт, char
подписан и int
имеет ширину в 32 бит и использует 2'-дополнение, то результат в шестнадцатеричном выражении будет выглядеть как 0xFFFFFFEF
(что отрицательное значение).
В-четвертых, спецификатор формата %x
требует аргумента unsigned int
, но вместо этого вы передаете аргумент int
с потенциально отрицательным значением. Поведение не определено.
Другими словами, ваша программа - просто большая куча неопределенного и определенного по реализации поведения. Нет смысла пытаться объяснить, почему вы получили этот конкретный результат.
Это неопределенное поведение, но вы просто берете младший байт (0xef) - потому что, по-видимому, ваша система немного суетна, а затем обрабатывает его как int и sign-extend. –
@ user3411451: Почему вы игнорируете диагностические сообщения от вашего компилятора? Инициализация 'b' с' & a' является незаконной. Если вы действительно хотите это сделать, вы должны использовать явное приведение. – AnT
Всегда запускайте свой компилятор в строжайшем режиме проверки ошибок. * По крайней мере * это должно включать '-Wall -Werror' (если используется GCC), и есть * lots * дополнительных доступных вариантов предупреждения. – DevSolar