For an assignment, I\'m trying to make some code in C that uses only bit manipulation to test if an integer is an ASCII uppercase letter. The letter will be given by its ASCII c
You can test if an ASCII letter c
is upper case by checking its 0x20
bit, it must be 0
for uppercase and 1
for lowercase:
if (!(c & 0x20))
printf("ASCII letter %c is uppercase\n", c);
but be aware that this test does not work if you don't already know that c
is a letter. It would erroneously match '@'
and '['
, '\\'
, ']'
, '^'
and '_'
, and the whole range of characters with the high bit set from 192 to 223, which are not part of ASCII but are valid unsigned char
values.
If you want a single test to verify if c
is an uppercase ASCII letter, try:
if ((unsigned)(c - 'A') <= (unsigned)('Z' - 'A'))
printf("%c is an uppercase ASCII letter\n", c);
EDIT: it is unclear what you mean by I am not allowed to use if statements, or any kind of type casting operations. I must test to see if the number is between the two numbers, including numbers far outside the range of the ASCII code, and return 1 if it is or else 0.
c
is a letter, both !(c & 0x20)
and (((c >> 5) & 1) ^ 1)
will have value 1
if c
is uppercase and 0
if not.c
can be any integer value, just write the regular comparison (c >= 'A' && c <= 'Z')
and the compiler will produce better code than you would by attempting hazardous bit-twiddling tricks.EDIT again:
Since c
can be any integer value and you are only allowed bit manipulations, here is another solution: !((c >> 5) ^ 2) & (0x07fffffeU >> (c & 31))
. Below is a program to test this:
#include
#include
static int uppertest(int c) {
return !((c >> 5) ^ 2) & (0x07fffffeU >> (c & 31));
}
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
int c = strtol(argv[i], NULL, 0);
printf("uppertest(%d) -> %d\n", c, uppertest(c));
}
return 0;
}