strchr
функция в стандартной библиотеке C ищет a char
в строке, но ее подписи берет int
для поискового символа. В этих двух реализациях я нашел, реализация бросает это int
к a char
:
char *strchr(const char *s, int c) {
while (*s != (char)c)
if (!*s++)
return 0;
return (char *)s;
}
char *strchr(const char *s, int c) {
while (*s && *s != (char)c)
s++;
if (*s == c)
return (char *)s;
return NULL;
}
Кто-либо знает почему? Почему не просто берут a char
в качестве параметра?
Причины этого чисто исторические. Обратите внимание, что в старые времена языка C (K&R C) не существовало такой вещи, как прототип функции . В то время функция strchr
объявлялась как
char *strchr();
и определялась в стиле K&R как
char *strchr(s, c)
char *s;
char c;
{
/* whatever */
}
. Однако на языке C (в K&R C и в современном), если функция была объявлена без прототипа (как показано выше) параметры, передаваемые при каждом вызове функции, подвергаются так называемому продвижению аргументов по умолчанию . При продвижении аргументов по умолчанию любой целочисленный тип меньше int
(или unsigned int
) всегда преобразуется в int
(или unsigned int
). Т.е. когда параметры не объявлены, всякий раз, когда вы передаете значение char
в качестве аргумента, это значение неявно преобразуется в int
и фактически физически передается как ] int
. То же верно и для короткого
.(Кстати, float
преобразуется в double
по умолчанию для продвижений аргументов). Если внутри функции параметр фактически объявлен как char
(как в определении стиля K&R выше), он неявно преобразуется обратно в тип char
и используется как char
внутри функции. Вот как это работало во времена K&R, и на самом деле так это работает по сей день в современном C, когда функция не имеет прототипа или когда используются вариативные параметры.
Теперь реплика в современном 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 *
, а затем использовать это объявление с предварительно скомпилированной устаревшей версией стандартной библиотеки, где malloc
фактически вернул char *
.
Ссылка: обоснование C99, версия 5.10
7.1.4 Использование библиотечных функций
/ - /
Все прототипы библиотек указаны в терминах «Расширенные» типы: аргумент, ранее объявленный как char, теперь записывается как int. Этот гарантирует, что большинство библиотечных функций может быть вызвано с прототипом или без него в области видимости, тем самым сохраняя обратную совместимость с кодом до C89
В c тип символьного литерала - int
. Например: 'a' имеет тип int
.
Я думаю, это можно объяснить не чем иным, как исторической случайностью. Вы совершенно правы, что char
кажется очевидным типом данных, который следует использовать для искомого символа.
В некоторых ситуациях в библиотеке C, таких как функция getc ()
, значение int
возвращается для символа, считанного из ввода. Это не char
, потому что дополнительное несимвольное значение ( EOF
, обычно -1) может быть возвращено, чтобы указать конец символьного потока.
Случай EOF
не применяется к функции strchr ()
, но они не могут сейчас вернуться и изменить объявление функции в библиотеке C.