I'm looking through the source code of a project written in C. Here is a list of options that are defined开发者_如何学Go (no these aren't the real defines...not very descriptive!)
...
#define OPTION_5 32768
#define OPTION_6 65536
#define OPTION_7 0x20000L
#define OPTION_8 0x40000L
#define OPTION_9 0x80000L
I'd like to add a new option OPTION_10
but before I do that, I'd like to understand what exactly the hex numbers represent?
Do these numbers convert to the expected decimal values of 131,072 262,144 524,288 ? If so, why not keep the same format as the earlier options?
Do these numbers convert to the expected decimal values of 131,072
Yes. You can use Google for the conversion: search for "0x20000 in decimal".
If so, why not keep the same format as the earlier options?
I guess simply because programmers know their powers of two up to 65536 and prefer hexadecimal, where they are more recognizable, above that.
The L
suffix forces the literal constant to be typed at least as a long int
, but the chosen type may be still larger if that's necessary to hold the constant. It's probably unnecessary in your program and the programmer used it because s/he didn't understand the emphasized clause. The nitty-gritty details are in 6.4.4.1, page 56 of the C99 standard.
Just a further thought to add to the existing answers, I prefer to define such flags more like this:
enum {
OPTION_5_SHIFT = 15,
OPTION_6_SHIFT,
OPTION_7_SHIFT,
OPTION_8_SHIFT,
OPTION_9_SHIFT,
OPTION_10_SHIFT
};
enum {
OPTION_5 = 1L << OPTION_5_SHIFT,
OPTION_6 = 1L << OPTION_6_SHIFT,
OPTION_7 = 1L << OPTION_7_SHIFT,
OPTION_8 = 1L << OPTION_8_SHIFT,
OPTION_9 = 1L << OPTION_9_SHIFT,
OPTION_10 = 1L << OPTION_10_SHIFT
};
This avoids having explicitly calculated constants and makes it much easier to insert/delete values, etc.
They represent the same kind of numbers, they are all powers of two. Or, too see it in a different light, they are all binary numbers with exactly one one (no phun intended).
One possible reason why they are written the they way they are (even though the reason isn't a good one) is that many programmers know the following sequence by hart:
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
This sequence corresponds to the first 17 powers of two. Then things are not that easy any more, so they probably switched to hex (being too lazy to change all the earlier numbers).
The specific values represent bit flag options, which can be combined with the bitwise OR operator |
:
flags = (OPTION_5|OPTION_6);
You will see from the binary representation of these values, that each has one unique bit set, to allow combining them using bitwise OR:
0x8000L = 32768 = 00000000 00000000 10000000 00000000
0x10000L = 65536 = 00000000 00000001 00000000 00000000
0x20000L = 131072 = 00000000 00000010 00000000 00000000
0x40000L = 262144 = 00000000 00000100 00000000 00000000
0x80000L = 524288 = 00000000 00001000 00000000 00000000
0x100000L = 1048576 = 00000000 00010000 00000000 00000000
To find out if a flag has been set in the flags variable, you can use the bitwise AND operator &
:
if(flags & OPTION_6)
{
/* OPTION_6 is active */
}
Each digit of a number represents a multiplication factor of the number's numerical system's base to the power of the digit's position in the number, counted from right to left, beginning with zero.
So 32768 = 8 * 10^0 + 6 * 10^1 + 7 * 10^2 + 2 * 10^3 + 3 * 10^4.
(Hint for the sake of completeness: x^0 = 1, x^1 = x.)
Hexadecimal numbers have 16 digits (0 - 9, A (~10) - F (~15)) and hence a base of 16, so 0x20 = 0 * 16^0 + 2 * 16^1.
Binary numbers have 2 digits and a base of 2, so 100b = 1 * 2^2 + 0 * 2^1 + 0 * 2^0.
Knowing that you should be able to figure the rest yourself and handle binary and hexadecimal numbers, understand that each number you listed is twice its predecessor, what decimal values the hex numbers have, what the next decimal number in the row should be, and how to express OPTION_10 in any numerical system, and particularly binary, decimal and hexadecimal.
精彩评论