Каково макро определение isupper в C? - PullRequest
3 голосов
/ 04 августа 2010

Я хочу знать, как макрос "isupper" определен в C / C ++.Не могли бы вы предоставить мне то же самое или указать мне доступные ресурсы.Я попытался посмотреть на ctype.h, но не смог понять.

Ответы [ 4 ]

12 голосов
/ 04 августа 2010

Это определяется реализацией - каждый поставщик может и обычно делает это по-своему.

Наиболее распространенным обычно является таблица «черт» - массив с одним элементом для каждого символа, значениеЭлемент, представляющий собой коллекцию флагов, указывает на детали о персонаже.Примером может быть:

 traits[(int) 'C'] = ALPHA | UPPER | PRINTABLE;

В этом случае isupper () будет выглядеть примерно так:

 #define isupper(c) ((traits[(int)(c)] & UPPER) == UPPER)
5 голосов
/ 04 августа 2010

Это зависит от реализации. Один очевидный способ реализовать это будет:

extern char *__isupper;
#define isupper(x) ((int)__isupper[(x)])

Где __isupper указывает на массив из 0 и 1, определяемый локалью. Однако этот вид техники потерял популярность, поскольку доступ к глобальным переменным в общих библиотеках довольно неэффективен и создает постоянные требования ABI, а также потому, что он несовместим с локальными языковыми стандартами POSIX.

Другой очевидный способ реализовать его в реализациях только для ASCII или UTF-8:

#define isupper(x) ((unsigned)(x)-'A'<='Z'-'A')
5 голосов
/ 04 августа 2010

Это функция, а не макрос.Определение функции isupper() отличается в зависимости от таких вещей, как языковой стандарт и текущий набор символов - поэтому есть функция, специально предназначенная для этой цели.

Для ASCII из-за способа назначения букв это на самом деле довольнолегко проверить это.Если ASCII-код символа находится в пределах от 0x41 до 0x5A включительно, то это заглавная буква.

1 голос
/ 04 августа 2010

На самом деле это довольно сложно, например, в GCC. Но простая реализация isupper может быть (хотя она имеет ошибку двойной оценки), наиболее просто определяемая как:

# определить isupper (c) (c> = 'A') & (c <= 'Z') </p>

http://ideone.com/GlN05

GCC специально проверяет бит 0 на 1 в символе для текущей локали:

(* __ctype_b_loc ()) [(int) (c)] & (unsigned short int) (1 << (0)) </p>

Где __ctype_b_loc () - это функция, которая возвращает указатель на массив символов в текущей локали, который содержит характеристики для каждого символа в текущем наборе символов.

...