Ответ 1
Причины этого носят чисто исторический характер. Обратите внимание, что в старые времена языка C (K & R C) прототипа функции не было. Функция strchr
в те времена будет объявлена как
char *strchr();
и определяется в стиле K & R как
char *strchr(s, c)
char *s;
char c;
{
/* whatever */
}
Однако, в языке C (в K & RC и в современной), если функция объявлена без прототипа (как показано выше), параметры, переданные в каждом вызове функции, подвергаются так называемым рекламным объявлениям по умолчанию, При стандартных рекламных акциях по умолчанию любой интегральный тип, меньший, чем int
(или unsigned int
), всегда преобразуется в int
(или unsigned int
). То есть когда параметры не объявлены, всякий раз, когда вы передаете значение char
в качестве аргумента, это значение неявно преобразуется в int
и фактически физически передается как int
. То же самое верно для short
. (BTW, float
преобразуется в double
по умолчанию для продвижения по умолчанию). Если внутри функции параметр фактически объявлен как char
(как указано выше в определении стиля K & R), он неявно преобразуется обратно в тип char
и используется как char
внутри функции. Вот как это работает в K & R раз, и на самом деле это так, как это работает по сей день в современном C, когда функция не имеет прототипа или когда используются вариационные параметры.
Теперь, cue в современном C, который имеет прототипы функций и использует синтаксис определения функции в современном стиле. Чтобы сохранить и воспроизвести "традиционные" функциональные возможности strchr
, как описано выше, у нас нет другого выбора, кроме как объявить параметр strchr
как int
и явно преобразовать его в char
внутри функции, Это именно то, что вы наблюдаете в коде, который вы указали. Это точно так же, как функциональные возможности strchr
описаны в стандарте.
Кроме того, если у вас уже скомпилированная устаревшая библиотека, где strchr
определяется в стиле K & R, как показано выше, и вы решили предоставить современные прототипы для этой библиотеки, правильное объявление для strchr
будет
char *strchr(const char *s, int c);
потому что int
- это то, что ожидает предыдущая реализация, физически получаемая как c
. Объявление его с параметром char
будет неправильным.
По этой причине вы никогда не увидите "традиционные" стандартные библиотечные функции, ожидающие параметры типа char
, short
или float
. Все эти функции будут объявлены с параметрами типа int
или double
.
В основе стандартной гарантии лежит то же самое, что указатели char и указатели void *
имеют одинаковые требования к представлению и выравниванию. Опираясь на эту гарантию, вы можете объявить malloc
как функцию void *
-returning, а затем использовать это объявление с предварительно скомпилированной старой версией стандартной библиотеки, где malloc
действительно возвращен char *
.
Ссылка: логика C99, версия 5.10
7.1.4 Использование библиотечных функций
/-/
Все прототипы библиотек указаны в терминах "расширенных" типов: аргумент, ранее объявленный как char, теперь записывается как int. Эта гарантирует, что большинство функций библиотеки можно вызвать с помощью или без прототипа в объеме, что обеспечивает обратную совместимость с код pre-C89