Почему strchr берет интервал для символа, который будет найден?

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 в качестве параметра?

20
задан templatetypedef 11 December 2011 в 05:32
поделиться

3 ответа

Причины этого чисто исторические. Обратите внимание, что в старые времена языка 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

37
ответ дан 29 November 2019 в 23:48
поделиться

В c тип символьного литерала - int. Например: 'a' имеет тип int.

3
ответ дан 29 November 2019 в 23:48
поделиться

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

В некоторых ситуациях в библиотеке C, таких как функция getc () , значение int возвращается для символа, считанного из ввода. Это не char , потому что дополнительное несимвольное значение ( EOF , обычно -1) может быть возвращено, чтобы указать конец символьного потока.

Случай EOF не применяется к функции strchr () , но они не могут сейчас вернуться и изменить объявление функции в библиотеке C.

3
ответ дан 29 November 2019 в 23:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: