2013-07-03 9 views
11

В C строки являются массивами символов char (char *) и символы обычно хранятся в char. Я заметил, что некоторые функции из libC берутся за целые числа аргументов вместо char.Почему putchar, toupper, tolower и т. Д. Берут int вместо char?

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

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

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

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

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

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

+3

Я не знаю ни одного правила, 'EOF' должны соответствовать в' char', и я могу заверить вас, что 'char' не гарантированно будет подписан, что делает ваше обсуждение об использовании' char' вместо 'unsigned char' кажутся неправильными. Вы имеете в виду «подписанный символ». –

+0

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

+1

Прочтите следующее: [Определение EOF и способы его эффективного использования] (http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284351&answer=1048865140) –

ответ

7

C11 7,4

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

С11 7.21.1

EOF

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

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

C11 6.2.5

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

+0

Один из моих вопросов: почему функция, которая преобразует письмо в другую, должна принимать то, что не является буквой? (Включенный EOF) –

1

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

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

+1

Да, но в тех местах, где это важно , в стандарте C говорится «unsigned char или EOF». –

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)) { 
    ... 
    } 
    ... 
} 
+0

У меня +1 ваш ответ для примера использования. Но, как вы сказали, это обескураживает, так почему 'isdigit' должен принимать то, что не является персонажем? –

+0

@Maxime Я уверен, что исторически это 'isdigit()' принимает '-1'. Концептуально, не сложно думать о EOF как о другом «char». Функции 'isthis ...()' часто реализуются с 256-байтным массивом, что делает 257-байтовый массив, чтобы также принимать EOF (-1), тривиально. Поскольку он прост и подходит для более жесткого кода, назад, когда жесткий код имеет более высокую ценность, его хорошее расширение. Теперь, с поддержанием кода каждого возрастающего значения, эта идиома потеряла пользу. – chux