bitRead() description

What type of numbers can bitRead() read properly?

The bit functions are simple macros defined in core wiring.h file. I’m not sure what restrictions they have on variable types they can work with, so I too would be interested in any answers the software gurus might offer.

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))


A macro is a simple text replacement in code, so if you wrote

int x=bitRead(5,2);

It would 'expand' into

int x=(((5) >> (2)) & 0x01);

And then get compiled. They are typeless - they'll expand anything, and then the compiler is left to deal with the result - for example, this will compile, but what did the programmer mean?

x=bitRead('o','k'); // ?

It's this lack of type casting that makes them hard to debug, since you have to figure out how the macro expanded, and where the syntax error crept in. Despite that, they can be very useful.

I general dislike any C macros. They only create problems when you don’t pay attention.

In this case since the bit is not cast to any type, it defaults to integer so you don’t worry about this. Here’s reference on >>, which is used in bitread:


variable - (byte, int, long) number_of_bits integer <= 32

So the bit you shift can be as many as 32. So 32 is your max in bitread’s bit.

They only create problems when you don't pay attention.

Not true. They can create problems even when you do pay attention. Especially when the macro is defined in some file included by some file included by some file included by the IDE, and is documented like a function.

I hate those that pretend a macro is a function in documentations instead of saying it is a macro, especially those macros that uses its argument more than once in itself. You do crapyMacro(arg++) and all hell breaks loose.

Indeed the designer(s) of Java specifically banned macros from the Java language for these sorts of reasons.

I don’t believe all macros are bad - but I like to tame them a bit by writing them in ALL CAPS, and not hiding them. Also, I try to avoid side effects - max() is a notorious example of that if you use ++ with any of the parameters.

In particular, I find them useful to add compiler framework - for instance, I’ve written an ASSERT() style macro that disappears completely when you turn on/off a compiler switch - on a small-memory device like the Arduino, being able to delete huge chunks of code like that is quite handy.

David, I am intrigued. What big chunk of code can you delete on arduino projects without getting into trouble?

What big chunk of code can you delete on arduino projects without getting into trouble?

Debug code.

liudr: David, I am intrigued. What big chunk of code can you delete on arduino projects without getting into trouble?

Code assertions are an example, and look like this:

assert(x==1); // blows up the program if x!=1

During debug, this would show on the screen and the program would die, giving you some info. When you compile without NDEBUG set, the entire line, and all the code behind, evaporates. The reason is that although it looks like a function, it is a macro wrapper for a function, allowing the file name, line number, etc to be inserted.

However, the Assert() macro is rather limited, so I'm planning on porting over a variation of my Asserting macro:

If anyone is interested, please let me know and I can post it here.