Почему putchar, toupper, tolower и т.д. Берут int вместо char?

В C строки являются массивами char (char *), и символы обычно хранятся в char. Я заметил, что некоторые функции из libC принимают за целые числа аргументов вместо char.

Например, возьмем функции toupper() и tolower(), которые используют int. На странице руководства написано:

Если c не является значением без знака char или EOF, поведение этих функции undefined.

Я предполагаю, что с int, toupper и tolower могут иметь дело с unsigned char и EOF. Но на самом деле EOF на практике (есть ли какое-либо правило о его значении?) Значение, которое может быть сохранено с помощью char, и поскольку эти функции не преобразуют EOF во что-то другое, мне интересно почему toupper не просто принимает аргумент char.

В любом случае, почему нам нужно принимать что-то, что не является символом (например, EOF)? Может ли кто-нибудь предоставить мне соответствующий прецедент?

Это похоже на fputc или putchar, которые также принимают int, который в любом случае преобразован в unsigned char.

Я ищу точные мотивы для этого выбора. Я хочу убедиться, я не хочу отвечать, что не знаю, спросит ли кто-нибудь меня однажды.

Ответ 1

C11 7.4

Заголовок <ctype.h> объявляет несколько функций, полезных для классификации и сопоставления персонажи. Во всех случаях аргументом является int, значение которого должно быть представляемый как unsigned char или должен равняться значению макрос EOF. Если аргумент имеет любое другое значение, поведение undefined.

C11 7.21.1

EOF

который расширяется до целочисленного постоянного выражения, с типом int и a отрицательное значение,...

В стандарте C явно указано, что EOF всегда является int с отрицательным значением. Кроме того, подпись стандартного типа char определяется реализацией, поэтому она может быть неподписанной и не способна сохранять отрицательное значение:

C11 6.2.5

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

Ответ 2

BITD включен способ кодирования:

/* example */
int GetDecimal() {
  int sum = 0;
  int ch;
  while (isdigit(ch = getchar())) { /* isdigit(EOF) return 0 */
    sum *= 10;
    sum += ch - '0';
    }
  ungetc(ch, stdin);  /* If c is EOF, operation fails and the input stream is unchanged. */
  return sum;
}

ch со значением EOF затем может использоваться в различных функциях, таких как isalpha(), tolower().

Этот стиль вызвал проблемы с putchar(EOF), который, как я подозревал, сделал то же самое, что и putchar(255).

Метод обескуражен сегодня по различным причинам. Предпочтительными являются следующие модели:

int GetDecimal() {
  int ch;
  while (((ch = getchar()) != EOF)) && isdigit(ch)) {
    ...
  }
  ...
}

Ответ 3

Если c не является значением без знака char или EOF, поведение этих функций равно undefined.

Но EOF является отрицательным int в C, а некоторые платформы (hi ARM!) имеют char то же самое, что и unsigned char.