2015-06-09 3 views
0

Этот макрос находится в «dosname.h» из coreutils.Что делает макрос make_is_drive_letter?

# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \ 
<= 'z' - 'a') 

Может кто-нибудь объяснить это мне?

+0

[Этот внутренний макрос принимает ASCII, но все хосты, которые поддерживают привод буквы использовать ASCII] (http://sourceforge.net/p/pimd-ng/git/ci/1dd3c80702f5f48bebf979b2966ee6f33d430625/tree/lib/dosname.h) – haccks

+0

Как вы думаете, что он делает? –

ответ

4

Он проверяет, является ли данный символ допустимой буквой для обозначения диска (например, «C» в «C: \ Something» обычно используется для обозначения основного жесткого диска) в MS-DOS- основанные на операционной системе.

Это эффективный способ проверить, соответствует ли символ регулярным выражениям [a-zA-Z] (английские буквы алфавита, как в верхнем, так и в нижнем регистре).

Он делает это, сначала устраняя различия между строчными и прописными буквами, используя побитовое «или» операцию |. В общем случае потребуется дополнительное сложение: добавьте расстояние между нижним регистром 'a' и верхним регистром 'A', если код ASCII находится ниже одного из 'A'. Но поскольку в ASCII разница между строчным символом и его соответствующим верхним регистром всегда равна 32 (= 2^5 = 100000b), а диапазон строчных букв меньше 32, мы видим, что единственная разница в двоичном представлении строчной буквы, а соответствующая верхняя буква - 6-й бит, например 1000001b == A и 1100001b == a. Таким образом, мы можем преобразовать буквы верхнего регистра в строчные буквы, установив 6-й бит, используя | с 32 (== 'a' - 'A') в качестве второго операнда. Это сделает странные вещи для всех других персонажей, которые не являются буквами, но они никогда не преобразуют их в письмо. Этот трюк работает более эффективно (без использования условия).

Тогда он проверяется, если символ (теперь это нижний регистр, если раньше это была верхняя буква) находится между 'a' и 'z'. Это делается путем вычитания из символа 'a' и проверки, если результат меньше числа символов. Это работает, потому что в ASCII английские символы одного и того же случая определяются как непрерывная последовательность.

+0

Спасибо, я понял. Не могли бы вы дать мне больше пояснений относительно кода. –

+0

Просто, надеюсь, это поможет. – mastov

+0

@ mayailias - это ответ мастова, который недостаточно хорош для вашей домашней работы? –

3
# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \ 
<= 'z' - 'a') 

('a' - 'A') - нижний регистр.

(C) | ('a' - 'A') установить нижний регистр в C. (теперь C может находиться между 'a' и 'z', но может быть и любым другим).

'z' - 'a' вычислить диапазон между буквами 'a' и 'z' (так 25, для буквы 'a' (0) в букву 'z' (25)).

Сравнение <= проверяет, что «C» преобразован в нижний регистр и смещен в 0, начиная с буквы «a», между 0 и 25, поэтому между буквами «a» и «z» (так, это действительная буква диска для MS-DOS).

Смежные вопросы