Why is this line obfuscated? - c

In this snippet,
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
{
/* statements */
}
the member OscillatorType could have any of the values, or their combination, defined below.
#define RCC_OSCILLATORTYPE_NONE ((uint32_t)0x00000000)
#define RCC_OSCILLATORTYPE_HSE ((uint32_t)0x00000001)
#define RCC_OSCILLATORTYPE_HSI ((uint32_t)0x00000002)
#define RCC_OSCILLATORTYPE_LSE ((uint32_t)0x00000004)
#define RCC_OSCILLATORTYPE_LSI ((uint32_t)0x00000008)
Why is the if written this way? Why not simply like this?
if(RCC_OscInitStruct->OscillatorType == RCC_OSCILLATORTYPE_HSI)

RCC_OscInitStruct->OscillatorType is a collection of bits packed in an integer value, each bit representing one of the values (RCC_OSCILLATORTYPE_HSE, ...). That's why they come in powers of 2. The code you showed just checks if the bit associated with RCC_OSCILLATORTYPE_HSI is set. It's very probable that bits of other values are also set.
For example if the binary representation of OscillatorType is 0...011, the first and second bit is set, meaning that the RCC_OSCILLATORTYPE_HSE and RCC_OSCILLATORTYPE_HSI values are selected.

It's a very common C idiom and not obfuscated in any way. Those are two very different tests.
if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
says "if the RCC_OSCILLATOR_HSI bit is 1". It doesn't care whether any of the other bits are 0 or 1, whereas
if (RCC_OscInitStruct->OscillatorType == RCC_OSCILLATORTYPE_HSI)
says "if the RCC_OSCILLATOR_HSI bit is 1 AND all the other bits are 0".

Because it may have any of these values at the same time. The & (bitwise AND) operator is serving the purpose of extracting only the value RCC_OSCILLATOR_TYPE_HSI.
As an example, your input may look like this:
010011
While RCC_OSCILLATOR_TYPE_HSI looks like this:
000010
The AND operator with these two values will return 000010, witch exactly equals RCC_OSCILLATOR_TYPE_HSI.
However, if your input looks like this:
110101
The bitwise AND operator between this and RCC_OSCILLATOR_TYPE_HSI will return 0, and the condition will be false.

The if condition is interested only in the second last bit of RCC_OscInitStruct->OscillatorType. So RCC_OSCILLATORTYPE_HSI is used as a mask and then compared to itself.
If you see all the constants, first one is all zeroes where as the others have its set bit at successive positions.
Now, doing & with any of these constants can tell you whether its corresponding bit is set in the said parameter.
If you want to set all of the possible values, you would be doing:
RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI;
Why comparison using ==?
That's not required and makes the code cluttered. I think that the programmer wanted to bring uniformity when testing for RCC_OSCILLATORTYPE_NONE.
The programmer can't test for RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_NONE because that would evaluate to zero. You are either forced to negate the condition just for this check.

An example:
#include <stdio.h>
#include <stdint.h>
#define RCC_OSCILLATORTYPE_NONE ((uint32_t)0x00000000)
#define RCC_OSCILLATORTYPE_HSE ((uint32_t)0x00000001)
#define RCC_OSCILLATORTYPE_HSI ((uint32_t)0x00000002)
#define RCC_OSCILLATORTYPE_LSE ((uint32_t)0x00000004)
#define RCC_OSCILLATORTYPE_LSI ((uint32_t)0x00000008)
int main(void)
{
/* set HSI and HSE */
uint32_t flags = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI;
if (flags == RCC_OSCILLATORTYPE_HSI) {
puts("flags = HSI");
}
if ((flags & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) {
puts("HSI is set in flags");
}
return 0;
}
Output:
HSI is set in flags

To begin with, == is not equivalent with &. Because == looks at the whole 32 bit register, including any crap you aren't interested in. While & just looks at the relevant parts.
And the & is simple binary arithmetic for bitwise AND. In my opinion, you need to understand binary numbers before even enrolling your first programmer course, but maybe that's just me.
Anyway, given that you actually understand what bitwise AND does, it would have made more sense if you had code like
#define RCC_OSCILLATORTYPE ((uint32_t)0x0000000F) // mask
#define RCC_OSCILLATORTYPE_NONE ((uint32_t)0x00000000)
#define RCC_OSCILLATORTYPE_HSE ((uint32_t)0x00000001)
#define RCC_OSCILLATORTYPE_HSI ((uint32_t)0x00000002)
#define RCC_OSCILLATORTYPE_LSE ((uint32_t)0x00000004)
#define RCC_OSCILLATORTYPE_LSI ((uint32_t)0x00000008)
...
(RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE) == RCC_OSCILLATORTYPE_HSI
Maybe this is what the programmer of that code intended, but they didn't quite manage to bring the code all the way there.

Related

C program using inotify help in understanding code

I was referring the man page for inotify and I came across this piece of code
if (event->mask & IN_ISDIR)
printf(" [directory]\n");
else
printf(" [file]\n");
where event is a pointer to struct inotify_event.
I couldn't understand this particular line if (event->mask & IN_ISDIR) and why a bitwise AND is used here.
How was it determined that the bitwise AND is supposed to be used here and nothing else? It was not mentioned in the man page for inotify.
This bitwise AND is masking out a specific bit (IN_ISDIR). It is testing whether or not this one bit is set or not. If this bit is set in event->mask, it evaluates to true.
For example,
#include <stdio.h>
#define FIRST_BIT 1
#define SECOND_BIT 2
#define THIRD_BIT 4
int main() {
int x = 3; /* 3 in binary is 011 */
if ( x & FIRST_BIT )
printf("First bit is set\n");
if ( x & SECOND_BIT )
printf("Second bit is set\n");
if ( x & THIRD_BIT )
printf("Third bit is set\n");
}
will give the output
First bit is set
Second bit is set
From inotify.h:
#define IN_ISDIR 0x40000000 /* event occurred against dir */
This value has only one bit set. (In binary, this is 01000000000000000000000000000000.) A bitwise AND with this (0x40000000) and some variable will evaluate to either 0 (if the variable has a 0 here), or 0x40000000 if the variable has a 1 in the same place. Any non-zero value is considered "true".
Logically, it is testing if the event was from a directory (instead of a file).
A bitwise AND is just an easy (and very common) way to check if a specific bit is set.
The man page is clear that if that bit is set then the event is referring to a directory.

C macros: Conditional code based on parameter value?

Is there a cleaner/simpler way to do this?
The below works OK, but I think it's ugly - I'd like a solution that doesn't need a separate #define for every possible invalid value passed as "port".
#define _port_A_config_digital(mask) // do nothing; this port is always digital
#define _port_B_config_digital(mask) AD1PCFGSET = (mask)
#define _port_C_config_digital(mask)
#define _port_D_config_digital(mask)
#define _port_E_config_digital(mask)
#define _port_F_config_digital(mask)
#define _port_G_config_digital(mask)
#define _port_H_config_digital(mask)
#define _port_I_config_digital(mask)
#define _port_J_config_digital(mask)
#define _port_K_config_digital(mask)
#define ConfigDigitalBits(port, mask) _port_##port##_config_digital(mask)
If "port" is anything other than B, I want a null statement.
I'd like to get rid of all the #defines other than the one that does something.
I want to do this because on this MCU all ports other than B are always digital and there's nothing to be done.
But calling ConfigDigitalBits() ought to be a valid thing to do for any port.
You could do something like
#define CONFIG_DIGITAL_BITS(PORT, MASK) \
do { if (PORT == 'B') AD1PCFGSET = (MASK); } while (0)
and trust (or check by reading the assembly) your compiler to evaluate the if condition at compile-time. That is,
CONFIG_DIGITAL_BITS('B', 0x42);
would generate code for only
AD1PCFGSET = 0x42;
and
CONFIG_DIGITAL_BITS('A', 0x42);
would generate no code at all.
The proposed code above has the problem that it ignores errors. For example,
CONFIG_DIGITAL_BITS('Z', 0x42);
would happily compile although there is no port Z. You could assert on this but this will only catch the error at run-time.
Once you got to this, consider getting rid of the macro at whole and use an inline function instead that will also permit constant propagation.
inline void
config_digital_bits(const char port, const unsigned mask)
{
assert(port >= 'A' && port <= 'K');
if (port == 'B')
AD1PCFGSET = mask;
}

C - Why compare constants with & instead of switch/if?

I am reading the OpenSL documentation for Android. Quoting the following document: http://mobilepearls.com/labs/native-android-api/ndk/docs/opensles/
"Callback handlers should be prepared to be called more or less frequently, to receive additional event types, and should ignore event types that they do not recognize. Callbacks that are configured with an event mask of enabled event types should be prepared to be called with multiple event type bits set simultaneously. Use "&" to test for each event bit rather than a switch case."
Checking the official specification of OpenSL (https://www.khronos.org/registry/sles/specs/OpenSL_ES_Specification_1.0.1.pdf), there are these 3 constants defined I am interested in:
SL_PREFETCHSTATUS
#define SL_PREFETCHSTATUS_UNDERFLOW ((SLuint32) 0x00000001)
#define SL_PREFETCHSTATUS_SUFFICIENTDATA ((SLuint32) 0x00000002)
#define SL_PREFETCHSTATUS_OVERFLOW ((SLuint32) 0x00000003)
If I understood correctly, the quote above says to compare using &, like this:
if(status & SL_PREFETCHSTATUS_UNDERFLOW) doSomething_1();
if(status & SL_PREFETCHSTATUS_SUFFICIENTDATA) doSomething_2();
if(status & SL_PREFETCHSTATUS_OVERFLOW) doSomething_3();
Instead of a switch case:
switch(statusCode){
case(SL_PREFETCHSTATUS_UNDERFLOW): doSomething_1(); break;
case(SL_PREFETCHSTATUS_SUFFICIENTDATA): doSomething_2(); break;
case(SL_PREFETCHSTATUS_OVERFLOW): doSomething_3(); break;
}
Now, I don't understand why that is exactly. Can anyone explain me the reason?
PS: If the constants were defined in multiples of 2, like this:
#define SL_PREFETCHSTATUS_UNDERFLOW ((SLuint32) 0x00000001)
#define SL_PREFETCHSTATUS_SUFFICIENTDATA ((SLuint32) 0x00000002)
#define SL_PREFETCHSTATUS_OVERFLOW ((SLuint32) 0x00000004)
It would make sense, but the specification defines the last constant as 0x00000003 instead of 0x00000004, so I am lost.
That comment is in reference to the event constants. What you're looking at are not event constants, but rather status constants. Event constants would be for example:
#define SL_PLAYEVENT_HEADATEND ((SLuint32) 0x00000001)
#define SL_PLAYEVENT_HEADATMARKER ((SLuint32) 0x00000002)
#define SL_PLAYEVENT_HEADATNEWPOS ((SLuint32) 0x00000004)
#define SL_PLAYEVENT_HEADMOVING ((SLuint32) 0x00000008)
#define SL_PLAYEVENT_HEADSTALLED ((SLuint32) 0x00000010)
You can see these are bitmask values and could be combined. Since they can be combined you need to compare the individual bits rather than the whole value to ensure you correctly match against the events you're interested in.
The documentation makes it clear:
Callbacks that are configured with an event mask of enabled event types should be prepared to be called with multiple event type bits set simultaneously.
This means that despite the flags not being bitwise, there still remains the possibility that multiple flags are set. The other flags being set might not necessarily be publicly-defined, but could be private, reserved or otherwise undocumented but still necessary for the system to function.
...so using a switch is not a good idea because then this fails:
SLuint32 statusCode = SL_PRIVATE_RESERVED_INTERNAL_USE_ONLY | SL_PREFETCH_STATUS_UNDERFLOW;
switch( statusCode ) {
case SL_PREFETCH_STATUS_UNDERFLOW:
// this code will never be executed
break;
}
Using & does bitwise comparison. So a & b gives a non-zero results if any of the bits are set in both a and b. That is not the same as comparing the values (for a given non-zero value of a, there are multiple values of b that can give a match).

Can you perform fixed-length bit reversal in #defines / preprocessor directives?

I am writing C code (not c++) for a target with very limited ROM, but I want the code to be easy to customize for other similar targets with #defines. I have #defines used to specify the address and other values of the device, but as a code-saving technique, these values are necessary bitwise reversed. I can enter these by first manually reversing them, but this would be confusing for future use. Can I define some sort of macro that performs a bitwise reversal?
As seen here (Best Algorithm for Bit Reversal ( from MSB->LSB to LSB->MSB) in C), there is no single operation to switch the order in c. Because of this, if you were to create a #define macro to perform the operation, it would actually perform quite a bit of work on each use (as well as significantly increasing the size of your binary if used often). I would recommend manually creating the other ordered constant and just using clear documentation to ensure the information about them is not lost.
I think something like this ought to work:
#define REV2(x) ((((x)&1)<<1) | (((x)>>1)&1))
#define REV4(x) ((REV2(x)<<2) | (REV2((x)>>2)))
#define REV8(x) ((REV4(x)<<4) | (REV4((x)>>4)))
#define REV16(x) ((REV8(x)<<8) | (REV8((x)>>8)))
#define REV32(x) ((REV16(x)<<16) | (REV16((x)>>16)))
It uses only simple operations which are all safe for constant expressions, and it's very likely that the compiler will evaluate these at compile time.
You can ensure that they're evaluated at compile time by using them in a context which requires a constant expression. For example, you could initialize a static variable or declare an enum:
enum {
VAL_A = SOME_NUMBER,
LAV_A = REV32(VAL_A),
};
For the sake of readable code I'd not recommend it, but you could do something like
#define NUMBER 2
#define BIT_0(number_) ((number_ & (1<<0)) >> 0)
#define BIT_1(number_) ((number_ & (1<<1)) >> 1)
#define REVERSE_BITS(number_) ((BIT_1(number_) << 0) + (BIT_0(number_) << 1))
int main() {
printf("%d --> %d", NUMBER, REVERSE_BITS(NUMBER));
}
There are techniques for this kind of operation (see the Boost Preprocessor library, for example), but most of the time the easiest solution is to use an external preprocessor written in some language in which bit manipulation is easier.
For example, here is a little python script which will replace all instances of #REV(xxxx)# where xxxx is a hexadecimal string with the bit-reversed constant of the same length:
#!/bin/python
import re
import sys
reg = re.compile("""#REV\(([0-9a-fA-F]+)\)#""")
def revbits(s):
return "0X%x" % int(bin(int(s, base=16))[-1:1:-1].ljust(4*len(s), '0'), base=2)
for l in sys.stdin:
sys.stdout.write(reg.sub(lambda m: revbits(m.group(1)), l))
And here is a version in awk:
awk 'BEGIN{R["0"]="0";R["1"]="8";R["2"]="4";R["3"]="C";
R["4"]="2";R["5"]="A";R["6"]="6";R["7"]="E";
R["8"]="1";R["9"]="9";R["A"]="5";R["B"]="D";
R["C"]="3";R["D"]="B";R["E"]="7";R["F"]="F";
R["a"]="5";R["b"]="D";R["c"]="3";R["d"]="B";
R["e"]="7";R["f"]="F";}
function bitrev(x, i, r) {
r = ""
for (i = length(x); i; --i)
r = r R[substr(x,i,1)]
return r
}
{while (match($0, /#REV\([[:xdigit:]]+\)#/))
$0 = substr($0, 1, RSTART-1) "0X" bitrev(substr($0, RSTART+5, RLENGTH-7)) substr($0, RSTART+RLENGTH)
}1' \
<<<"foo #REV(23)# yy #REV(9)# #REV(DEADBEEF)#"
foo 0X32 yy 0X9 0Xfeebdaed

What does this enum mean?

I saw this line of code today and had no idea what it does.
typedef enum {
SomeOptionKeys = 1 << 0 // ?
} SomeOption;
Some usage or example would be helpful. Thanks!
It looks like it defines an enumerated type that is supposed to contain a set of flags. You'd expect to see more of them defined, like this:
typedef enum {
FirstOption = 1 << 0,
SecondOption = 1 << 1,
ThirdOption = 1 << 2
} SomeOption;
Since they are defined as powers of two, each value corresponds to a single bit in an integer variable. Thus, you can use the bitwise operators to combine them and to test if they are set. This is a common pattern in C code.
You could write code like this that combines them:
SomeOption myOptions = FirstOption | ThirdOption;
And you could check which options are set like this:
if (myOptions & ThirdOption)
{
...
}
The value of SomeOptionKeys is one, this is a useful representation when working with flags:
typedef enum {
flag1 = 1 << 0, // binary 00000000000000000000000000000001
flag2 = 1 << 1, // binary 00000000000000000000000000000010
flag3 = 1 << 2, // binary 00000000000000000000000000000100
flag4 = 1 << 3, // binary 00000000000000000000000000001000
flag5 = 1 << 4, // binary 00000000000000000000000000010000
// ...
} SomeOption;
Whit way each flag has only one bit set, and they could be represented in a bitmap.
Edit:
Although, I have to say, that I might be missing something, but it seems redundent to me to use enums for that. Since you lose any advantage of enums in this configuration, you may as well use #define:
#define flag1 (1<<0)
#define flag2 (1<<1)
#define flag3 (1<<2)
#define flag4 (1<<3)
#define flag5 (1<<4)
It just sets the enum to the value 1. It is probably intended to indicate that the values are to be powers of 2. The next one would maybe be assigned 1 << 1, etc.
<< is the left shift operator. In general, this is used when you want your enums to mask a single bit. In this case, the shift doesn't actually do anything since it's 0, but you might see it pop up in more complex cases.
An example might look like:
typedef enum {
OptionKeyA = 1<<0,
OptionKeyB = 1<<1,
OptionKeyC = 1<<2,
} OptionKeys;
Then if you had some function that took an option key, you could use the enum as a bitmask to check if an option is set.
int ASet( OptionKeys x){
return (x & OptionKeyA);
}
Or if you had a flag bitmap and wanted to set one option:
myflags | OptionKeyB

Resources