473,511 Members | 16,252 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Mathew Hendry's macro for binary integer literals


Here's a macro that Mathew Hendry posted back in the year 2000 for
achieving binary integer literals that evaluate to compile-time
constants:

#define BIN8(n)\
(((0x##n##ul&1<< 0)>0)|((0x##n##ul&1<< 4)>3)\
|((0x##n##ul&1<< 8)>6)|((0x##n##ul&1<<12)>9)\
|((0x##n##ul&1<<16)>>12)|((0x##n##ul&1<<20)>>15)\
|((0x##n##ul&1<<24)>>18)|((0x##n##ul&1<<28)>>21))

Now admittedly I don't know how it works mathematically, but still I
want to perfect it. The first thing I did was made it more readable
(in my own opinion of course):

#define BIN8(n)\
(

((0x##n##ul & 1<<0) >0) | ((0x##n##ul & 1<<0) >>
3) \
| ((0x##n##ul & 1<<8) >6) | ((0x##n##ul & 1<<12)>>
9) \
| ((0x##n##ul & 1<<16)>>12) | ((0x##n##ul &
1<<20)>>15) \
| ((0x##n##ul & 1<<24)>>18) | ((0x##n##ul &
1<<28)>>21) \
)

From there, the only flaw I can see is in the expression "1 << 24",
which I think should be "1lu << 24", so that gives us:

#define BIN8(n)\
(

((0x##n##ul & 1lu<<0) >0) | ((0x##n##ul & 1lu<<0)
>3) \
| ((0x##n##ul & 1lu<<8) >6) | ((0x##n##ul &
1lu<<12)>9) \
| ((0x##n##ul & 1lu<<16)>>12) | ((0x##n##ul &
1lu<<20)>>15) \
| ((0x##n##ul & 1lu<<24)>>18) | ((0x##n##ul &
1lu<<28)>>21) \
)

Is that perfect now? Or does it need more tweaking? Even if you post
to say you think it's perfect then that'd be a help.

Jun 27 '08 #1
4 2553
Tomás Ó hÉilidhe wrote:
Here's a macro that Mathew Hendry posted back in the year 2000 for
achieving binary integer literals that evaluate to compile-time
constants:

#define BIN8(n)\
(((0x##n##ul&1<< 0)>0)|((0x##n##ul&1<< 4)>3)\
|((0x##n##ul&1<< 8)>6)|((0x##n##ul&1<<12)>9)\
|((0x##n##ul&1<<16)>>12)|((0x##n##ul&1<<20)>>15)\
|((0x##n##ul&1<<24)>>18)|((0x##n##ul&1<<28)>>21))

Now admittedly I don't know how it works mathematically
The 0, 4, 8, ... correspond to the "bit position" when interpreted as
a hexadecimal value.

For example, the "1" at '0b00100000' occupies bit 20 in 0x00100000,
so
0x00100000 & (1 << 20) isolates that bit, and
0x00100000 >15 "moves it (back) to its 'proper' hexadecimal
position.
, but still I
want to perfect it. The first thing I did was made it more readable
(in my own opinion of course):
... so that gives us:
>
#define BIN8(n)\
(

((0x##n##ul & 1lu<<0) >0) | ((0x##n##ul & 1lu<<0)
3) \
| ((0x##n##ul & 1lu<<8) >6) | ((0x##n##ul &
1lu<<12)>9) \
| ((0x##n##ul & 1lu<<16)>>12) | ((0x##n##ul &
1lu<<20)>>15) \
| ((0x##n##ul & 1lu<<24)>>18) | ((0x##n##ul &
1lu<<28)>>21) \
)

Is that perfect now?
Two things come to mind:

a) it doesn't cope well with usenet (re-)formatting
b) you have the original "ul" mixed with your "lu". I'd like it better
if all suffixes were the same.
Jun 27 '08 #2
On Jun 17, 6:51*am, badc0...@gmail.com wrote:
Tomás Ó hÉilidhe wrote:
Here's a macro that Mathew Hendry posted back in the year 2000 for
achieving binary integer literals that evaluate to compile-time
constants:
* #define BIN8(n)\
* * (((0x##n##ul&1<< 0)>0)|((0x##n##ul&1<< 4)>3)\
* * |((0x##n##ul&1<< 8)>6)|((0x##n##ul&1<<12)>9)\
* * |((0x##n##ul&1<<16)>>12)|((0x##n##ul&1<<20)>>15)\
* * |((0x##n##ul&1<<24)>>18)|((0x##n##ul&1<<28)>>21))
Now admittedly I don't know how it works mathematically

The 0, 4, 8, ... correspond to the "bit position" when interpreted as
a hexadecimal value.

For example, the "1" at '0b00100000' occupies bit 20 in 0x00100000,
so
0x00100000 & (1 << 20) isolates that bit, and
0x00100000 >15 "moves it (back) to its 'proper' hexadecimal
position.
, but still I
want to perfect it. The first thing I did was made it more readable
(in my own opinion of course):

... so that gives us:
#define BIN8(n)\
* * (
* * * * * * ((0x##n##ul & 1lu<<0) >0) * *| * * ((0x##n##ul & 1lu<<0)
>3) * *\
* * * * | * ((0x##n##ul & 1lu<<8) >6) * *| * * ((0x##n##ul &
1lu<<12)>9) * *\
* * * * | * ((0x##n##ul & 1lu<<16)>>12) * *| * * ((0x##n##ul &
1lu<<20)>>15) * *\
* * * * | * ((0x##n##ul & 1lu<<24)>>18) * *| * * ((0x##n##ul &
1lu<<28)>>21) * *\
* * )
Is that perfect now?

Two things come to mind:

a) it doesn't cope well with usenet (re-)formatting
b) you have the original "ul" mixed with your "lu". I'd like it better
if all suffixes were the same.
- Too much repetition. Adding 0x and UL can be done by a helper macro.

- Suggest parentheses for awkward precedence of & relative to <<:

#define HEX_CODED_BIN(N)\
(((N & 1 << 0) >0)|((N & 1 << 4) > 3)\
|((N & 1 << 8) >6)|((N & 1 << 12) > 9)\
|((N & 1 << 16) >>12)|((N & 1 << 20) >15)\
|((N & 1 << 24) >>18)|((N & 1 << 28) >21))
#define BIN8(BITS) HEX_CODED_BIN(0x ## BITS ## UL)

Furthermore, the shifting can be done first and then the masking,
which simplifies the choice of shift values:

#define HEX_CODED_BIN(N) \
((((N > 0) & 1) << 0) | (((N >16) & 1) << 4) | \
(((N > 4) & 1) << 1) | (((N >20) & 1) << 5) |\
(((N > 8) & 1) << 2) | (((N >24) & 1) << 6) | \
(((N >12) & 1) << 3) | (((N >28) & 1) << 7))

See? The logic is is a lot clearer now, because offsets in hex space
don't have to be translated into shift amounts in binary space. The 0,
4, 8, 12 ... values are obvious: we are shifting a hex digit into the
least significant digit position. The & 1 tells us we are masking out
a 0 or 1, and the 0, 1, 2, 3 ... shifts are obvious also: shifting a
bit into the correct position within the byte.

I transposed the calculation into columns, for further readability.

- Remark: A BIN32 macro is easy to make:

#define BIN32(A, B, C, D) \
(BIN8(A) << 24) | (BIN8(B) << 16) | (BIN8(C) << 8) | (BIN8(D))

- Complete program:

#include <stdio.h>

#define HEX_CODED_BIN(N) \
((((N > 0) & 1) << 0) | (((N >16) & 1) << 4) | \
(((N > 4) & 1) << 1) | (((N >20) & 1) << 5) | \
(((N > 8) & 1) << 2) | (((N >24) & 1) << 6) | \
(((N >12) & 1) << 3) | (((N >28) & 1) << 7))

#define BIN8(BITS) HEX_CODED_BIN(0x ## BITS ## UL)

#define BIN32(A, B, C, D) \
(BIN8(A) << 24) | (BIN8(B) << 16) | (BIN8(C) << 8) | (BIN8(D))

int main(void)
{
unsigned int bin1 = BIN8(10101010);
unsigned int bin2 = BIN8(01010101);
unsigned int bin3 = BIN8(11111111);
unsigned int bin4 = BIN8(00000000);
unsigned long bin5 = BIN32(10101010, 01010101, 11110000,
00001111);

printf("bin1 == %x\n", bin1);
printf("bin2 == %x\n", bin2);
printf("bin3 == %x\n", bin3);
printf("bin4 == %x\n", bin4);
printf("bin5 == %lx\n", bin5);

return 0;
}

Output:

bin1 == aa
bin2 == 55
bin3 == ff
bin4 == 0
bin5 == aa55f00f

Cheers.

Jun 27 '08 #3
On Jun 17, 6:51*pm, Kaz Kylheku <kkylh...@gmail.comwrote:
- Complete program:

#include <stdio.h>

#define HEX_CODED_BIN(N) \
* ((((N >*0) & 1) << 0) | (((N >16) & 1) << 4) | \
* *(((N >*4) & 1) << 1) | (((N >20) & 1) << 5) | \
* *(((N >*8) & 1) << 2) | (((N >24) & 1) << 6) | \
* *(((N >12) & 1) << 3) | (((N >28) & 1) << 7))

#define BIN8(BITS) HEX_CODED_BIN(0x ## BITS ## UL)

#define BIN32(A, B, C, D) \
* (BIN8(A) << 24) | (BIN8(B) << 16) | (BIN8(C) << 8) | (BIN8(D))

int main(void)
{
* * unsigned int bin1 = BIN8(10101010);
* * unsigned int bin2 = BIN8(01010101);
* * unsigned int bin3 = BIN8(11111111);
* * unsigned int bin4 = BIN8(00000000);
* * unsigned long bin5 = BIN32(10101010, 01010101, 11110000,
00001111);

* * printf("bin1 == %x\n", bin1);
* * printf("bin2 == %x\n", bin2);
* * printf("bin3 == %x\n", bin3);
* * printf("bin4 == %x\n", bin4);
* * printf("bin5 == %lx\n", bin5);

* * return 0;

}

Output:

bin1 == aa
bin2 == 55
bin3 == ff
bin4 == 0
bin5 == aa55f00f

Very nice, good stuff.
Jun 27 '08 #4
On Jun 17, 10:51*am, Kaz Kylheku <kkylh...@gmail.comwrote:
On Jun 17, 6:51*am, badc0...@gmail.com wrote:


Tomás Ó hÉilidhe wrote:
Here's a macro that Mathew Hendry posted back in the year 2000 for
achieving binary integer literals that evaluate to compile-time
constants:
* #define BIN8(n)\
* * (((0x##n##ul&1<< 0)>0)|((0x##n##ul&1<< 4)>3)\
* * |((0x##n##ul&1<< 8)>6)|((0x##n##ul&1<<12)>9)\
* * |((0x##n##ul&1<<16)>>12)|((0x##n##ul&1<<20)>>15)\
* * |((0x##n##ul&1<<24)>>18)|((0x##n##ul&1<<28)>>21))
Now admittedly I don't know how it works mathematically
The 0, 4, 8, ... correspond to the "bit position" when interpreted as
a hexadecimal value.
For example, the "1" at '0b00100000' occupies bit 20 in 0x00100000,
so
0x00100000 & (1 << 20) isolates that bit, and
0x00100000 >15 "moves it (back) to its 'proper' hexadecimal
position.
, but still I
want to perfect it. The first thing I did was made it more readable
(in my own opinion of course):
... so that gives us:
#define BIN8(n)\
* * (
* * * * * * ((0x##n##ul & 1lu<<0) >0) * *| * * ((0x##n##ul & 1lu<<0)
3) * *\
* * * * | * ((0x##n##ul & 1lu<<8) >6) * *| * * ((0x##n##ul &
1lu<<12)>9) * *\
* * * * | * ((0x##n##ul & 1lu<<16)>>12) * *| * * ((0x##n##ul &
1lu<<20)>>15) * *\
* * * * | * ((0x##n##ul & 1lu<<24)>>18) * *| * * ((0x##n##ul &
1lu<<28)>>21) * *\
* * )
Is that perfect now?
Two things come to mind:
a) it doesn't cope well with usenet (re-)formatting
b) you have the original "ul" mixed with your "lu". I'd like it better
if all suffixes were the same.

- Too much repetition. Adding 0x and UL can be done by a helper macro.

- Suggest parentheses for awkward precedence of & relative to <<:

* *#define HEX_CODED_BIN(N)\
* * *(((N & 1 << *0) >0)|((N & 1 << *4) >*3)\
* * *|((N & 1 << *8) >6)|((N & 1 << 12) >*9)\
* * *|((N & 1 << 16) >>12)|((N & 1 << 20) >15)\
* * *|((N & 1 << 24) >>18)|((N & 1 << 28) >21))

* *#define BIN8(BITS) HEX_CODED_BIN(0x ## BITS ## UL)

Furthermore, the shifting can be done first and then the masking,
which *simplifies the choice of shift values:

* *#define HEX_CODED_BIN(N) \
* * * ((((N >*0) & 1) << 0) | (((N >16) & 1) << 4) | \
* * * *(((N >*4) & 1) << 1) | (((N >20) & 1) << 5) |\
* * * *(((N >*8) & 1) << 2) | (((N >24) & 1) << 6) | \
* * * *(((N >12) & 1) << 3) | (((N >28) & 1) << 7))

See? The logic is is a lot clearer now, because offsets in hex space
don't have to be translated into shift amounts in binary space. The 0,
4, 8, 12 ... values are obvious: we are shifting a hex digit into the
least significant digit position. The & 1 tells us we are masking out
a 0 or 1, and the 0, 1, 2, 3 ... shifts are obvious also: shifting a
bit into the correct position within the byte.

I transposed the calculation into columns, for further readability.

- Remark: A BIN32 macro is easy to make:

* *#define BIN32(A, B, C, D) \
* * * (BIN8(A) << 24) | (BIN8(B) << 16) | (BIN8(C) << 8) | (BIN8(D))

- Complete program:

#include <stdio.h>

#define HEX_CODED_BIN(N) \
* ((((N >*0) & 1) << 0) | (((N >16) & 1) << 4) | \
* *(((N >*4) & 1) << 1) | (((N >20) & 1) << 5) | \
* *(((N >*8) & 1) << 2) | (((N >24) & 1) << 6) | \
* *(((N >12) & 1) << 3) | (((N >28) & 1) << 7))
Furthermore, this pattern can be easily reduced like this:

#define BIT(N, K) (((N >(4*K)) & 1) << K)

#define HEX_CODED_BIN(N) \
(BIT(N, 0) | BIT(N, 1) | BIT(N, 2) | BIT(N, 3) | \
BIT(N, 4) | BIT(N, 5) | BIT(N, 6) | BIT(N, 7))
Let's have some fun: how about a decimal version of this? Decimal
constants give us more digits (without having to go to C99).

#define POW10_0 1
#define POW10_1 10
#define POW10_2 100
#define POW10_3 1000
#define POW10_4 10000
#define POW10_5 100000
#define POW10_6 1000000
#define POW10_7 10000000
#define POW10_8 100000000
#define POW10_9 1000000000

#define POW10(K) POW10_ ## K

#define BIT(N, K) (((N / POW10(K)) % 2) << K)

#define DEC_CODED_BIN(N) \
(BIT(N, 0) | BIT(N, 1) | BIT(N, 2) | BIT(N, 3) | \
BIT(N, 4) | BIT(N, 5) | BIT(N, 6) | BIT(N, 7) | \
BIT(N, 8) | BIT(N, 9))

#define BIN10(N) DEC_CODED_BIN(N ## UL)

But this version has serious bug---or, at least, a programmer pitfall.
That bug brings me to the next point: if we switch to octal, we
portably get 11 digits!

#define BIT(N, K) (((N >(3*K)) & 1) << K)

#define OCT_CODED_BIN(N) \
(BIT(N, 0) | BIT(N, 1) | BIT(N, 2) | BIT(N, 3) | \
BIT(N, 4) | BIT(N, 5) | BIT(N, 6) | BIT(N, 7) | \
BIT(N, 8) | BIT(N, 9) | BIT(N, 10))

#define BIN11(N) OCT_CODED_BIN(0 ## N ## UL)

:)
Jun 27 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
22571
by: Bern | last post by:
how to specifiy a binary number in c++? hex numbers are specified by 0x prefix
4
52349
by: Vittal | last post by:
Hello All, Here is a small C program, main() { int a= 100; float b =99.99; TEST(a,%d); TEST(b,%f);
44
3685
by: Simon Morgan | last post by:
Hi, Can somebody please help me grok the offsetof() macro? I've found an explanation on http://www.embedded.com/shared/printableArticle.jhtml?articleID=18312031 but I'm afraid it still...
13
15550
by: Rick Anderson | last post by:
Group, I want to define a #include directive from another macro, if possible... For example, the following doesn't work but is basically what I need to do: #define...
6
1671
by: John Dann | last post by:
I'm trying to use a third party .Net charting control. One of its methods takes a standard 4-byte integer as a parameter (to specify a colour actually, but it's done as a standard integer value and...
11
10124
by: valerij | last post by:
Hi, what is the best way to hardcode into a C/C++ program binary values/constants/etc. Since: int a; a=0b0111; is wrong, how should I do it. I thought about converting them first to...
19
18809
by: sethukr | last post by:
Hi everybody, Can we assign binary values to an integer variable like assigning Hexadecimal values??? Thanks, Sethu
2
1269
by: John Dann | last post by:
I've obviously got a blind spot for binary arithmetic! Why can't I say: Dim x as uint32 = &HFFFFFFFF (which gives a 'Constant expression not representable' error in VB2005) 8 characters...
1
3363
by: todWulff | last post by:
Good day folks. Let me open with the statement that I am not a C++/C programmer. The environment that I am programming in is ARMbasic, an embedded BASIC targeted toward ARM-based...
0
7242
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7138
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7353
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7508
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5662
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5063
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4737
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3222
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
446
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.