Этот макрос находится в «dosname.h» из coreutils.Что делает макрос make_is_drive_letter?
# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
<= 'z' - 'a')
Может кто-нибудь объяснить это мне?
Этот макрос находится в «dosname.h» из coreutils.Что делает макрос make_is_drive_letter?
# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
<= 'z' - 'a')
Может кто-нибудь объяснить это мне?
Он проверяет, является ли данный символ допустимой буквой для обозначения диска (например, «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 английские символы одного и того же случая определяются как непрерывная последовательность.
Спасибо, я понял. Не могли бы вы дать мне больше пояснений относительно кода. –
Просто, надеюсь, это поможет. – mastov
@ mayailias - это ответ мастова, который недостаточно хорош для вашей домашней работы? –
# 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).
[Этот внутренний макрос принимает ASCII, но все хосты, которые поддерживают привод буквы использовать ASCII] (http://sourceforge.net/p/pimd-ng/git/ci/1dd3c80702f5f48bebf979b2966ee6f33d430625/tree/lib/dosname.h) – haccks
Как вы думаете, что он делает? –