Работа с целочисленным переполнением ctype.h - PullRequest
1 голос
/ 29 июня 2010

Как правильно обращаться с символьными значениями, которые при приведении к беззнаковому символу попадают между {INT_MAX + 1 ... UCHAR_MAX}, где UCHAR_MAX больше INT_MAX.

int is_digit(char c) {
    unsigned char uchar = c;
    if(uchar > INT_MAX)
        return MAYBE;
    return isdigit((int)uchar) ? YES : NO;
}

Ответы [ 2 ]

1 голос
/ 02 февраля 2012

Единственный способ, которым UCHAR_MAX будет больше, чем INT_MAX, это если вы работаете на машине с sizeof(int) == 1; то есть , где char имеет столько бит, сколько int.На этих машинах UCHAR_MAX = UINT_MAXINT_MAX.

На 32-разрядной (или более) машине это вряд ли будет проблемой.Пока значение в переменной c поступает из источника текста, я не знаю никакой текстовой кодировки, которая могла бы вызвать переполнение.Даже для UTF-32 будут активны только младшие 21 бит.(На самом деле, поскольку мы обсуждаем нечетные системы, я должен сказать, что это работает для машин с sizeof(int) = 1 и CHAR_BIT ≥ 22. ☺)

Если на такой машине, тем не менее, is_digit()передал аргумент c больше INT_MAX, он не пришел из источника текста .Неопределенное поведение является следствием помещения не символьных данных в переменную char, и это всегда будет то, что делал программист, , а не что-то, что было вызвано реализацией.

Существуетсистема, в которой эта может быть проблемой: 16-битные char и int, и система использовала 16-битный код символа ( например , UTF-16), гдестарший бит может быть установлен.Если это так, то реализации следует определить простой char как подписанный, именно по этой причине.Если подписано char, оно будет преобразовано в (подписано) int и может быть безопасно передано в семейство функций is*()char без знака он будет повышен до unsignedint, а приведение к знаку int может быть неопределенным.

В такой системе ваш код действительно не работает, но это будет ваша собственная ошибка для совершенно ненужного преобразования в unsigned char и опасного (в этой системе) приведения (int)uchar.

Подводя итог: В системах с sizeof(int) == 1 реализация несет ответственность за то, чтобы каждая точка кода, когда она хранится в переменной char, могла безопасно передаваться в функции ctype.h (которые ожидают int аргументов).Это может всегда быть сделано.Если вы сохранили что-то в переменной char, которая не является кодовой точкой, и передали это в is*(), то ответственность за неопределенное поведение лежит только на вас.

0 голосов
/ 29 июня 2010

Набор символов Unicode (который является наибольшим обычно используемым) имеет коды символов от 0 до 0x10ffff. Таким образом, единственная возможность для кода символа быть больше, чем INT_MAX, это если int является 16-битным типом (или, в частности, менее 22 бит). Если это так, то вы просто не можете сохранить код символа в int.

Если int - это 32-битный тип (или не менее 22 бит), то символьный код не будет переполнен при приведении к int.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...