2010-06-28 5 views
1

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

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

На какой машине вы находитесь, где 'UCHAR_MAX' больше, чем' INT_MAX'? –

+1

Должен ли я обслуживать весь мой код в отношении машины, на которой я работаю? –

ответ

0

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

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

+0

Вы всегда можете использовать utf-8 и/или массивы char для хранения отдельных кодовых точек. Независимо от этого факта. Строковые литералы состоят из символов, а функции ctype.h не работают с символами. Люди, которые писали C99, должны были подумать об этом случае в углу. –

+0

@Elite: Это угловой корпус? Знаете ли вы о какой-либо системе, которая использует полные 21-битные кодовые точки Unicode (т. Е. Хранит строки в UTF-32) и имеет 16-битный int? – Guffa

+0

Юникод ничего не имеет к делу. Сосредоточьтесь на этих двух фактах. У вас есть персонаж, и он имеет значение (ZOMG! Он может быть даже отрицательным). Такие функции, как isdigit, могут не принимать ваше значение. В заключение - функции ctype.h не являются надежными. –

1

Единственный способ 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*(), то виной за неопределенное поведение является ваш & ваш.