Я прочитал в книге Денниса Ритчи « Язык программирования C», которая int
должна использоваться для переменной, содержащей EOF - чтобы сделать ее достаточно большой, чтобы она могла содержать значение EOF, - нет char
. Но следующий код работает нормально:
#include<stdio.h>
main() {
char c;
c=getchar();
while(c!=EOF) {
putchar(c);
c=getchar();
}
}
Когда больше нет ввода, getchar
возвращает EOF. И в приведенной выше программе переменная c
с типом char может успешно его хранить.
Почему это работает? Согласно объяснениям в вышеприведенной книге, код не должен работать.
0xff
. Сохранение результатаgetchar()
в Апint
решает эту проблему. Ваш вопрос по сути такой же, как вопрос 12.1 в FAQ по comp.lang.c , который является отличным ресурсом. (Кроме того,main()
должно бытьint main(void)
, и это не мешало бы добавитьreturn 0;
до закрытия}
.)Ответы:
Ваш код, кажется, работает, потому что неявные преобразования типов случайно делают правильные вещи.
getchar()
возвращает значениеint
со значением, которое соответствует диапазонуunsigned char
или равноEOF
(которое должно быть отрицательным, обычно это -1). Обратите внимание, чтоEOF
сам по себе это не символ, а сигнал о том, что больше нет доступных символов.При сохранении результата из
getchar()
inc
есть две возможности. Любой типchar
может представлять значение, и в этом случае это значениеc
. Или типchar
не может представлять значение. В этом случае не определено, что произойдет. Процессоры Intel просто отсекают старшие биты, которые не вписываются в новый тип (эффективно уменьшая значение по модулю 256 дляchar
), но вы не должны на это полагаться.Следующий шаг - сравнить
c
сEOF
. КакEOF
иint
,c
будет также преобразованint
в, сохраняя значение, хранящееся вc
. Еслиc
можно сохранить значениеEOF
, тогда сравнение будет успешным, но еслиc
не удалось сохранить значение, то сравнение не удастся, поскольку при преобразованииEOF
в тип произошла безвозвратная потеря информацииchar
.Кажется, ваш компилятор решил сделать
char
тип подписанным, а значениеEOF
достаточно маленьким, чтобы уместитьсяchar
. Если бы ониchar
были без знака (или если бы вы использовалиunsigned char
), ваш тест не прошел бы, потому чтоunsigned char
не может содержать значениеEOF
.Также обратите внимание, что есть вторая проблема с вашим кодом. Поскольку
EOF
это не сам символ, но вы принудительно вводите его вchar
тип, существует весьма вероятный символ, который будет неправильно истолкован как существующий,EOF
и для половины возможных символов он не определен, если они будут обработаны правильно.источник
char
значений за пределами диапазонаCHAR_MIN
.CHAR_MAX
Будет необходимо либо для получения значения, определенного реализацией, либо для битового шаблона, который реализация определяет как представление прерывания, либо для выдачи сигнала, определенного реализацией. В большинстве случаев реализация должна была бы пройти большую дополнительную работу, чтобы сделать что-то кроме сокращения с двумя дополнениями. Если люди в Комитете по стандартам поддержали идею о том, что компиляторам следует поощрять к реализации поведения, согласующегося с поведением большинства других компиляторов, при отсутствии оснований поступать иначе ...(signed char)x
следует считать более ясным и таким же безопасным, как и((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1)
.) Как такового, я не вижу никакой вероятности компиляторы, реализующие любое другое поведение, соответствующее сегодняшнему стандарту; единственная опасность состоит в том, что Стандарт может быть изменен, чтобы нарушить поведение в предполагаемом интересе «оптимизации».int i=129; signed char c=i;
является одним из таких поведения. Относительно немногие процессоры имеют инструкцию, которая делала быc
равной,i
когда она находится в диапазоне от -127 до +127, и давала бы любое непротиворечивое отображение других значенийi
в значения в диапазоне от -128 до +127, которые отличались от сокращения на два дополнения, или. ..