Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Parameters in a single Parameter (functions) in C/C++

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!

like image 294
Jesse Brands Avatar asked Jan 02 '12 10:01

Jesse Brands


4 Answers

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.

like image 185
thiton Avatar answered Oct 29 '22 03:10

thiton


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
  // ..
}
like image 23
Gorpik Avatar answered Oct 29 '22 04:10

Gorpik


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.

like image 24
Serdalis Avatar answered Oct 29 '22 03:10

Serdalis


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.

like image 42
Shamim Hafiz - MSFT Avatar answered Oct 29 '22 04:10

Shamim Hafiz - MSFT