Как именно эта функция является примером преобразования char в int? - PullRequest
0 голосов
/ 26 декабря 2018

Книга Язык программирования C Кернигана и Ричи, второе издание, на странице 43 говорится в главе о Преобразованиях типов :

Другой примерпреобразованием char в int является функция lower, которая отображает один символ в нижний регистр для набора символов ASCII .Если символ не является заглавной буквой, lower возвращает его без изменений.

/* lower: convert c to lower case; ASCII only */
int lower(int c)
{
    if (c >= 'A' && c <= 'Z')
        return c + 'a' - 'A';
    else
        return c;
}

Это явно не упоминается в тексте, поэтому я хотел бы убедиться, что я его понимаюправильно: преобразование происходит при вызове функции lower с переменной типа char, не так ли?В частности, выражение

c >= 'A'

не имеет ничего общего с преобразованием из int в char, поскольку символьная константа, такая как 'A', обрабатывается как int внутренне с самого начала, не так ли 'не так ли?Изменить: Или это отличается (например, символьная константа рассматривается как char) для ANSI C, который охватывает книга?

Ответы [ 3 ]

0 голосов
/ 26 декабря 2018

K & R C стар.Действительно старый.Многие особенности K & R C больше не соответствуют действующему стандарту C.

В стандартном, современном C11 нет преобразования в / из char в опубликованной вами функции:

/* lower: convert c to lower case; ASCII only */
int lower(int c)
{
    if (c >= 'A' && c <= 'Z')
        return c + 'a' - 'A';
    else
        return c;
}

Функция принимает int аргументы в виде int c и по 6.4.4.4 Символьные константы стандарта C , символьные литералы имеют типint.

Таким образом, вся функция lower в том виде, в каком она была опубликована в C11, полностью работает со значениями int.

Преобразование, если оно есть, может быть выполнено, когда функцияназывается:

char upperA = 'A`;

// this will implicitly promote the upperA char
// value to an int value
char lowerA = lower( upperA );

Обратите внимание, что это одно из различий между C и C ++.В C ++ символьные литералы имеют тип char, а не int.

0 голосов
/ 26 декабря 2018

Как именно эта функция является примером преобразования char в int?

/* lower: convert c to lower case; ASCII only */
int lower(int c) {
    if (c >= 'A' && c <= 'Z')
        return c + 'a' - 'A';
    else
        return c;
}

Это не пример char в intпреобразование - технически некорректно автором.


В тексте обсуждается tolower(c) как альтернатива lower(), так как он "работает" правильно, даже если [A -Z] не кодируются последовательнокак в EBCDIC .

Что не обсуждается, так это то, что tolower() функции и другие (is...()) указаны только для значений int в диапазоне unsigned char и EOF.C11 §7.4 1. Другие значения вызывают неопределенное поведение (UB).

Именно это требование делает функции библиотеки Standard C концептуально char до int преобразования, так как указаны только значения в (около) char диапазоне, и результат равен int.


Теперь рассмотрим код, в котором char преобразование действительно происходит .

void my_strtolower1(char *s) {
  while (*s) {
    *s = lower(*s);  // conversion `char` to `int` and `int` to `char`.
    s++;
  }
} 

void my_strtolower2(char *s) {
  while (*s) {
    *s = tolower(*s); // conversion `char` to `int` and `int` to `char`.
    s++;
  }
} 

void my_strtolower3(char *s) {
  while (*s) {
    // conversion `char` to `unsigned char` to `int` and `int` to `char`.
    *s = tolower((unsigned char) *s); 
    s++;
  }
} 

my_strtolower1() четко определены, но функционально некорректны на редких машинах, где [A-Z,a-z] не являются последовательными.

my_strtolower2() ожидаемая функциональность, кроме технически неопределенного поведения при *s < 0(а не EOF).

my_strtolower3() ожидаемая функциональность без UB при *s < 0.

0 голосов
/ 26 декабря 2018

Символьные константы имеют тип int, как вы и ожидали, поэтому вы правы, что в этой функции нет повышения до int.

Любое повышение, которое может произойти, произойдет, если в эту функцию будет передана переменная типа char, и это, скорее всего, то, на что ссылается текст.

Тип символьных константравно int в обоих текущих C17 стандартах (раздел 6.4.4.4p10):

Целочисленная символьная константа имеет тип int

И в C89 / ANSI C стандарте (раздел 3.1.3.4 в разделе Семантика):

Целочисленная символьная константа имеет тип int

К последнему относится K & R Second Edition.

...