Ok this might sound a little vague from the title, but that's because I have no idea how to word it differently. I'll try to explain what I mean: very often in certain libraries, the 'init' function accepts some parameters, but that parameter then accepts multiple parameters (right..). An example, would be like this:
apiHeader.h
#define API_FULLSCREEN 0x10003003
#define API_NO_DELAY 0x10003004
#define API_BLAH_BLAH 0x10003005
main.c:
apiInit(0, 10, 10, 2, API_FULLSCREEN | API_NO_DELAY | API_BLAH_BLAH);
How does this work? I can't find the answer anywhere, most likely because I don't know how it's actually called so I have no clue what to search for. It would be very useful in my current project.
Thanks in advance!
The parameter is usually called "$FOO flags" and the values are or-ed. The point is that the parameter is a numeric type that is constructed as the bitwise or of multiple possible values.
In the processing functions, the values are usually tested with a bitwise and:
if ( (flags & API_FULLSCREEN) != 0 )
You have to be careful to assign values in a way that keeps the OR operation linear. In other words, don't set the same bit in two different or-able values, like you did in your header. For example,
#define API_FULLSCREEN 0x1
#define API_NO_DELAY 0x2
#define API_BLAH_BLAH 0x4
works and allows you to deconstruct all combinations of flags in your function, but
#define API_FULLSCREEN 0x1
#define API_NO_DELAY 0x2
#define API_BLAH_BLAH 0x3
does not because API_FULLSCREEN | API_NO_DELAY == API_BLAH_BLAH.
Viewing from a higher level, a flags int is a poor man's variable argument list. If you consider C++, you should encapsulate such detail in a class or at least a std::bitset.
This fifth parameter is usually a mask. It works by defining several consts (probably an enum) with values that are powers of two, or combinations of them. Then they are encoded into a single value using |, and decoded using &. Example:
#define COLOUR_RED 0x01
#define COLOUR_GREEN 0x02
#define COLOUR_BLUE 0x04
#define COLOUR_CYAN (COLOUR_BLUE | COLOUR_GREEN) // 0x06
// Encoding
SetColour(COLOUR_RED | COLOUR_BLUE); // Parameter is 0x05
// Decoding
void SetColour(int colour)
{
if (colour & COLOUR_RED) // If the mask contains COLOUR_RED
// Do whatever
if (colour & COLOUR_BLUE) // If the mask contains COLOUR_BLUE
// Do whatever
// ..
}
What they are doing there is using binary OR to combine the flags together.
so what is actually happening is:
0x10003003 | 0x10003004 | 0x10003005 == 0x10003007
It's still one parameter, but the 3 flags will combine to create a unique value for that parameter which can be used in the function.
What you are defining as multiple parameter is strictly a single parameter from the function signature point of view.
As for handling multiple Options based on a single parameter, as you can see there is the bitwise Or Operator which sets a single value for the parameter value. The body of the function then uses individual bits to determine the complete settings.
Usually, one bit is allocated for one option and they usually have two state(true/false) values.
The parameter is usually called "flags" and contains an or-ed combination of a set of allowed values.
int flags = API_FULLSCREEN | API_NO_DELAY;
The function can the take this integer parameter and extract the individual items like this:
int fullscreen_set = flags & API_FULLSCREEN;
int no_delay_set = flags & API_NO_DELAY;
int blah_blah_set = flags & API_BLAH_BLAH;
For this to work one has to be carfull in how one chooses the numeric values for the API_* parameters.
Bitwise OR
Bitwise OR works almost exactly the same way as bitwise AND. The only difference is that only one of the two bits needs to be a 1 for that position's bit in the result to be 1. (If both bits are a 1, the result will also have a 1 in that position.) The symbol is a pipe: |. Again, this is similar to boolean logical operator, which is ||.
01001000 | 10111000 = 11111000
and consequently
72 | 184 = 248
So In you Method not a multiple parameter it is actully one parameter.
you can use Bitwise OR opearation on API_FULLSCREEN | API_NO_DELAY | API_BLAH_BLAH and passed it in method.
The example that you gave will not work as expected. What you do is to use a particular bit for a particular option - and the OR combines then
Example
#define OPT1 1
#define OPT2 2
#define OPT3 4
So bit 1 is for OPT1, bit 2 is for OPT2 etc.
So OPT1 | OPT3 sets bit 1 and 3 and gives a value of 5
In the function you can test if a particular option is required using the AND operator
So
void perform(int opts)
{
if (opts & OPT1)
{
// Do stuff for OPT1
}
...
The value of these parameters are defined in a way that they don't have any overlap. Something like this:
#define A 0x01
#define B 0x02
#define C 0x04
#define D 0x08
Given the above definitions, your can always determine which of the above variables have been ORed using the bitwise AND operator:
void foo(int param)
{
if(param & A)
{
// then you know that A has been included in the param
}
if(param & B)
{
// then you know that B has been included in the param
}
...
}
int main()
{
foo (A | C);
return 0;
}
Related
I've been going through an old source project, trying to make it compile and run (it's an old game that's been uploaded to GitHub). I think a lot of the code was written with C-style/C-syntax in mind (a lot of typedef struct {...} and the likes) and I've been noticing that they define certain macros with the following style:
#define MyMacroOne (1<<0) //This equals 1
#define MyMacroTwo (1<<1) //This equals 2, etc.
So my question now is this - is there any reason why macros would be defined this way? Because, for example, 0x01 and 0x02 are the numerical result of the above. Or is it that the system will not read MyMacroOne = 0x01 but rather as a "shift object" with the value (1<<0)?
EDIT: Thanks for all of your inputs!
It makes it more intuitive and less error prone to define bit values, especially on multibit bitfields. For example, compare
#define POWER_ON (1u << 0)
#define LIGHT_ON (1u << 1)
#define MOTOR_ON (1u << 2)
#define SPEED_STOP (0u << 3)
#define SPEED_SLOW (1u << 3)
#define SPEED_FAST (2u << 3)
#define SPEED_FULL (3u << 3)
#define LOCK_ON (1u << 5)
and
#define POWER_ON 0x01
#define LIGHT_ON 0x02
#define MOTOR_ON 0x04
#define SPEED_STOP 0x00
#define SPEED_SLOW 0x08
#define SPEED_FAST 0x10
#define SPEED_FULL 0x18
#define LOCK_ON 0x20
It is convenient for the humans
for example
#define PIN0 (1u<<0)
#define PIN5 (1u<<5)
#define PIN0MASK (~(1u<<0))
#define PIN5MASK (~(1u<<5))
and it is easy too see if there is a correct bit position. it does not make the code slower as it is calculated at the compile time
You can always use constant integer expression shifts as a way to express (multiples of) powers of two, i.e. Multiple*(2 to the N-th power) = Mutliple << N (with some caveats related to when you hit the guaranteed size limits of the integer types and UB sets in*) and pretty much rely on the compiler folding them.
An integer expression made of integer constants is defined as an integer constant expression. These can be used to specify array sizes, case labels and stuff like that and so every compiler has to be able to fold them into a single intermediate and it'd be stupid not to utilize this ability even where it isn't strictly required.
*E.g.: you can do 1U<<15, but at 16 you should switch to at least 1L<<16 because ints/unsigneds are only required to have at least 16 bits and leftshifting an integer by its width or into the place where its sign bit is is undefined (6.5.7p4):
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated
bits are filled with zeros. If E1 has an unsigned type, the value of
the result is E1 x 2E2 , reduced modulo one more than the maximum
value representable in the result type. If E1 has a signed type and
nonnegative value, and E1 x 2E2 is representable in the result type,
then that is the resulting value; otherwise, the behavior is
undefined.
Macro are just replacement text. Everywhere macro is replaced by replacement text!! This is convenient especially if you want to name something constant which otherwise is prone to mistakes.
To illustrate how this (1<<0) syntax is more practical, consider this example from the code-base of Git 2.25 (Q1 2020), which moves the definition of a set of bitmask constants from 0ctal literal to (1U<<count) notation.
See commit 8679577 (17 Oct 2019) by Hariom Verma (harry-hov).
(Merged by Junio C Hamano -- gitster -- in commit 8f40d89, 10 Nov 2019)
builtin/blame.c: constants into bit shift format
Signed-off-by: Hariom Verma
We are looking at bitfield constants, and elsewhere in the Git source code, such cases are handled via bit shift operators rather than octal numbers, which also makes it easier to spot holes in the range.
If, say, 1<<5 was missing:
it is easier to spot it between 1<<4 and 1<<6
than it is to spot a missing 040 between a 020 and a 0100.
So instead of:
#define OUTPUT_ANNOTATE_COMPAT 001
#define OUTPUT_LONG_OBJECT_NAME 002
#define OUTPUT_RAW_TIMESTAMP 004
#define OUTPUT_PORCELAIN 010
You get:
#define OUTPUT_ANNOTATE_COMPAT (1U<<0)
#define OUTPUT_LONG_OBJECT_NAME (1U<<1)
#define OUTPUT_RAW_TIMESTAMP (1U<<2)
#define OUTPUT_PORCELAIN (1U<<3)
From what I understand, the bitwise inclusive OR operator compares every bit in the first and second operand and returns 1 if either bit is 1. Bjarne Stroustrup uses it like this (ist being an istream object):
ist.exceptions(ist.exceptions()|ios_base::bad_bit);
I haven't really worked with bits a lot in programming, should it be on my to-do list to learn? I understand that if I had an int and the value was 9, the binary would be 00001001, but that is pretty much it. I do not understand why he would use this operator in the context that he used it in.
In this case, it simply means "turn a bit on".
Just an example: I have a byte 0100 0011 serves as 8 booleans. I want to turn on 4th bit (i.e. make 4th boolean true)
By bitwise operation, it looks like this: [0100 0011] Bitwise-OR [0000 1000] and it will give you 0100 1011. Which means, it simply change 4th bit to true, regardless of its original value
You can think of it as a way to add an option to a set of existing options. An analogy would be if you're familiar with linux:
PATH = "$PATH:/somenewpath"
This says 'I want the existing path and this new path /somenewpath'
In this case he's saying 'I want the existing options in exceptions and I want the bad_bit option as well'
The std::ios::exceptions is a function which gets/sets an exception mask in the file which is used by the file object to decide in which situations it should throw an exception or not.
There exist two implementations of this function:
iostate exceptions() const; // get current bit mask
void exceptions (iostate except); // set new bit mask
The statement you've posted sets the new exception mask to the file object using ios_base::badbit flag combined with the current flags, that are currently set in the file object.
The OR bitwise operator is often used in order to create create a bitfield using already existing bitfield and a new flag. It could also be used in order to combine two flags together into a new bitfield.
Here is an example with explanation:
// Enums are usually used in order to represent
// the bitfields flags, but you can just use the
// constant integer values.
// std::ios::bad_bit is, actually, just a constant integer.
enum Flags {
A,
B,
C
};
// This function is similar to std::ios::exceptions
// in the sense that it returns a bitfield (integer,
// in which bits are manipulated directly).
Something foo() {
// Return a bitfield in which A and B flags
// are "on".
return A | B;
}
int main() {
// The actual bitfield, which is represented as a 32-bit integer
int bf = 0;
// This is what you've seen (well, somethng similar).
// So, we're assigning a new bitfield to the variable bf.
// The new bitfield consists of the flags which are enabled
// in the bitfield which foo() returns and the C flag.
bf = foo() | C;
return 0;
}
#include <opcodes.h>
const char *getOpcodeName(
uint8_t op
)
{
#define OPCODE(x, y) if((0x##y)==op) return "OP_" #x;
OPCODES
#undef OPCODE
return "OP_UNKNOWN";
}
Link to the code here: https://github.com/znort987/blockparser/blob/master/opcodes.cpp
Here is a link to the included opcodes.h
I understand this is just a strangely formatted function, however, I am wondering what exactly the * at the beginning of the function name means. I assume it has something to do with pointers?
Also, how are the #undef and #define statements valid? There's no semicolon after either one, and one of them seems to be defined as a one-line function. What does (0x##y) mean? What does return "OP_" #x mean? I haven't ever come across syntax like this before.
I want to get into C++ more seriously, but it's very hard when looking at code to tell what exactly is going on. How can I learn the syntax and rules most effectively?
Run your code thru a C++ preprocessor, e.g. using g++ -Wall -C -E opcodes.cpp > opcodes.i then look inside the generated opcodes.i
#define is not a statement but a preprocessor directive.
The macro OPCODES gets expanded to some big chunk, notably containing OPCODE( NOP, 61) which would get expanded to something like
if ((0x61)==op) return "OP_" "NOP";
The two string literals are concatenated into one, "OP_NOP" here.
GCC has a good documentation on its cpp preprocessor. Read about stringification (with the single # like the ending #x; of the OPCODE macro) and about concatenation (with a double ## like (0x##y) of the OPCODE macro).
Short answer: This function converts opcodes to string.
The * IS RELATED to do with pointers! in fact, this function returns a const char * type. This is a pointer for a char buffer (in this case) used to point to a C-String. Every C-String is actually a buffer with "readable characteres" (alphanumerical, some accents, basic symbols + some stuff) followed by a byte of value 0 (or '\0') to indicate the end of the string!
This function converts opcodes (assembly instructions) to a readable string. So The intention of the programmer was to transform:
0x01 -> OP_CODE1
0x02 -> OP_CODE2
0x03 -> OP_CODE3
The expanded version of the code is something like this:
const char *getOpcodeName( uint8_t op )
{
if((0x01)==op) return "OP_X";
if((0x02)==op) return "OP_Y";
if((0x03)==op) return "OP_Z";
...
if((0x??)==op) return "OP_?";
return "OP_UNKNOWN";
}
Insted of write houndreds of IF's ... the programmer decided to create the macro
#define OPCODE(x, y) if((0x##y)==op) return "OP_" #x;
So it's possible to write the OPCODES table easily like this:
#define OPCODES \
OPCODE( 01, "X" ) \
OPCODE( 02, "Y" ) \
OPCODE( 03, "Z" ) \
...
OPCODE( ??, "?" )
Opcodes are codes that indentify the processor instruction (assembly instructions). Example of real instructions (for some Intel processor) are:
inc eax ; opcode = 0x40
pusha ; opcode = 0x60
nop ; opcode = 0x90
So your table could be:
#define OPCODES \
OPCODE( 40, "INCEAX" ) \
OPCODE( 60, "PUSHA" ) \
OPCODE( 90, "NOP" )
How is the following macro definition resolved?
#define EMAIL_SERVER_ADAPTER_FATAL_ERROR MSB_RETURN_TYPE_FATAL_ERROR | 1
I mean, is it resolved to 1 or to MSB_RETURN_TYPE_FATAL_ERROR and why?
| has no special meaning in macros. The macro is resolved to
MSB_RETURN_TYPE_FATAL_ERROR | 1
which is bitwise OR of two values (MSB_RETURN_TYPE_FATAL_ERROR and 1).
The | in the macro has the same meaning as elsewhere in C and C++. It means bitwise or.
Presumable MSB_RETURN_TYPE_FATAL_ERROR is some numeric value (otherwise it won't compile, pretty much).
For arguments sake, we'll make it 0x100
So the following code:
return EMAIL_SERVER_ADAPTER_FATAL_ERROR;
will expand to:
return MSB_RETURN_TYPE_FATAL_ERROR | 1;
which in turn becomes:
return 0x100 | 1;
which in turn is the same as:
return 0x101;
Of course MSB_RETURN_TYPE_FATAL_ERROR is probably something other than 0x100 - but the principle still applies.
Macros are just text replacement, so
EMAIL_SERVER_ADAPTER_FATAL_ERROR
will be substituted for
MSB_RETURN_TYPE_FATAL_ERROR | 1
After that it is just numbers (i.e. plain bit-wise OR operation).
I'm learning about bit-flags. I already know how they work and how they are defined in a struct. However, I'm unsure if they can be defined in a #define preprocessor directive like this:
#define FLAG_FAILED:1
Is this preprocessor define directive the as a struct bit-flag definition?
PS: I've already come across this related question but it didn't answer my question: #defined bitflags and enums - peaceful coexistence in "c". Also, if you can point me towards some information regarding preprocessor directives, I would appreciate that.
Any #define that you want to use to inject bitflags into a struct must take the form:
#define IDENTIFIER SUBSTITUTED_CODE
In your postulated use...
#define FLAG_FAILED:1
The identifier contains the colon, which makes it invalid.
You could do something like this:
#define FLAG_FAILED int flag_failed :1
struct X
{
char a;
FLAG_FAILED;
int b;
...
};
It's not clear why you're considering using a define for the bit field anyway. If you just want to be able to vary the field length, then:
#define FLAG_FAILED_BITS 1
struct X
{
unsigned flag_failed :FLAG_FAILED_BITS;
};
...or...
#define FLAG_FAILED_BITS :1
struct X
{
unsigned flag_failed FLAG_FAILED_BITS;
};
#define FLAG_FAILED:1 is not really a bit flag in the sense that what most people know as a "bit flag". It's also bad syntax.
Bit flags typically are defined so that you have a type and you turn "on" bits by "setting" them. You turn them "off" by "clearing" the flag. To compare if the bit flag is on, you use what is called the bitwise operator AND (e.g. &).
So your BIT0 (e.g. 2^0) would be defined as BIT0 = 0x00000001 and BIT1 (e.g. 2^1) as BIT1 = 0x00000002. If you wanted to stick with define you could do it this way with setting and clearing:
#ifndef setBit
#define setBit(word, mask) word |= mask
#endif
#ifndef clrBit
#define clrBit(word, mask) word &= ~mask
#endif
or as a template
template<typename T>
inline T& setBit(T& word, T mask) { return word |= mask; }
template<typename T>
inline T& clrBit(T& word, T mask) { return word &= ~mask; }
If you want to set the bit, so to speak, you could have a state set as follows:
setBit(SystemState, SYSTEM_ONLINE);
or
setBit(SystemState, <insert type here>SYSTEM_ONLINE);
clearing would be the same just replace setBit with clrBit.
To compare, just do this:
if (SystemState & SYSTEM_ONLINE) { ... // do some processing
}
if this is in a struct then, reference the struct.
A form to define bitwise values with #define macros is:
#define BIT_ONE static_cast<int>( 1 << 0 )
#define BIT_TWO static_cast<int>( 1 << 1 )
#define BIT_THREE static_cast<int>( 1 << 2 )