Как работает приведение char-указателя к int-указателю? - PullRequest
0 голосов
/ 21 мая 2019

Я изучаю C. Когда я проходил там указатели, я заметил странное поведение, которое я не могу понять.При приведении символьного указателя к целочисленному указателю целочисленный указатель содержит какое-то странное значение, не имеющее разумной связи с кодом char или char ascii.Но пока печатается приведенная переменная с помощью «% c», она печатает правильное значение символа.

Печать с использованием «% d» дает некоторые неизвестные числа.

printf("%d", *pt); // prints as unknown integer value that too changes for every run

Но при печати как «% c», тогда

printf("%c", *pt); // prints correct casted char value

Вся программа:

int main() {

char f = 'a';
int *pt = (int *)&f;

printf("%d\n", *pt);
printf("%c\n", *pt);

return 0;
}

Пожалуйста, объясните, как работает приведение символов к типу int и укажите объяснениевыходное значение.

Редактировать:

Если я внесу следующие изменения в программу, то вывод будет таким, как ожидалось.Пожалуйста, объясните это тоже.

#include <stdio.h>

int main() {

char f = 'a';
int *pt = (int *)&f;

printf("%d\n", *pt);
printf("%c\n", *pt);

int val = (int)f;
printf("%d\n", val);
printf("%c", val);
return 0;
}

Вывод:

97
a
97
a

Пожалуйста, объясните это поведение тоже.

Ответы [ 2 ]

5 голосов
/ 21 мая 2019

Для того, что указывает язык C, это просто неопределенное поведение. У вас есть область памяти размером char, из которой вы читаете int; результат не определен.

Что касается того, что, вероятно, происходит: среда выполнения C заканчивает тем, что выбрасывает некоторый случайный мусор в стек до того, как main даже будет выполнен. char f = 'a'; случается так, что один байт мусора перезаписывается на известное значение, но заполнение для выравнивания pt означает, что оставшиеся байты никогда не перезаписываются вообще, и в них есть «все, что осталось после выполнения». Поэтому, когда вы читаете int в системе с прямым порядком байтов, младший байт равен значению 'a', но старшие байты - это любой мусор, оставшийся в области заполнения.

Что касается того, почему %c работает, поскольку младший байт остается тем же самым, а %c проверяет только младший байт предоставленного int, весь мусор игнорируется, и все происходит так, как ожидается. Это работает только на маленькой порядковой машине; на машине с прямым порядком байтов это будет высокий байт, инициализированный до 'a', но младший байт (мусор) будет напечатан как %c.

1 голос
/ 21 мая 2019

Вы определяете f как char . Это обычно выделяет 1 байт памяти в большинстве аппаратных средств. Вы берете адрес f , приводите его к (int *) и назначаете его переменной int *, pt. Размер целого числа зависит от базового оборудования - это может быть 2 или 4 или даже больше. При назначении адреса f на pt адрес, который назначается для pt, зависит от таких факторов, как размер int и требования к выравниванию. Вот почему, когда вы печатаете * pt , вы видите значение мусора. На самом деле значение ASCII 'a' содержится в мусоре, положение которого зависит от размера int, порядкового номера оборудования и т. Д. Если вы печатаете * pt с % x , вы увидите 61 на выходе (61 гекс - 97 в десятичном виде). ​​

...