Bit flags in C/C++
Siempre me ha parecido muy útil el paso de parámetros por medio de banderas de bits (más conocidas como bit flags). En muchas de las librerías que he ido manejando estos últimos años he observado que es muy común pasar opciones, a por ejemplo una función, mediante un argumento de tipo int (32 bits) y de esta forma poder pasar un número de opciones igual al número de bits empleados por el tipo de dato. A continuación es dejo un ejemplo muy sencillo para que veáis como se suele utilizar los bits flags en C/C++.
// =====================================================================================
//
// Filename: bitflags.cpp
//
// Description: How to use combination of flags in your programs
//
// Version: 1.0
// Created: 24/01/10 10:51:53
// Revision: none
// Compiler: g++
//
// Author: Luis Díaz Más
// Company: http://plagatux.es
//
// =====================================================================================
#include
#include
#include
#include
using namespace std;
// ##### VARIABLES - LOCAL TO THIS SOURCE FILE ################################
static const char short_options [] ="abcdefghi";
#ifdef __linux
static const struct option long_options [] =
{
{ "help", no_argument, NULL, 'h'},
{ "optiona", no_argument, NULL, 'a'},
{ "optionb", no_argument, NULL, 'b'},
{ "optionc", no_argument, NULL, 'c'},
{ "optiond", no_argument, NULL, 'd'},
{ "optione", no_argument, NULL, 'e'},
{ "optionf", no_argument, NULL, 'f'},
{ "optiong", no_argument, NULL, 'g'},
{ "optioni", no_argument, NULL, 'i'},
{ 0, 0, 0, 0 }
};
#endif // __linux -----
enum options {
optiona = 0x01, // 00000001
optionb = 0x02, // 00000010
optionc = 0x04, // 00000100
optiond = 0x08, // 00001000
optione = 0x10, // 00010000
optionf = 0x20, // 00100000
optiong = 0x40, // 01000000
optioni = 0x80, // 10000000
}; // ---------- end of enum options ----------
static unsigned int myoptions=0;
// ##### FUNCTION DEFINITIONS - LOCAL TO THIS SOURCE FILE #####################
static void usage();
static void readArguments ( int argc,char **argv );
// === FUNCTION ======================================================================
// Name: main
// Description:
// =====================================================================================
int main ( int argc, char *argv[] )
{
try
{
readArguments(argc, argv);
cout << "Value of myoptions: " << myoptions << endl;
// Match with only one option
if (myoptions & optiona) cout << "optiona enabled\n";
if (myoptions & optionb) cout << "optionb enabled\n";
if (myoptions & optionc) cout << "optionc enabled\n";
if (myoptions & optiond) cout << "optiond enabled\n";
if (myoptions & optione) cout << "optione enabled\n";
if (myoptions & optionf) cout << "optionf enabled\n";
if (myoptions & optiong) cout << "optiong enabled\n";
if (myoptions & optioni) cout << "optioni enabled\n";
// Match with several options
if (myoptions & (optiona | optionb)) cout << "a + b \n";
if (myoptions & (optiona | optionc)) cout << "a + c \n";
if (myoptions & (optiond | optioni)) cout << "a + c \n";
}
catch (exception &ex)
{
cout << ex.what() << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // ---------- end of function main ----------
// === FUNCTION ======================================================================
// Name: usage
// Description:
// =====================================================================================
static void usage()
{
cout<<"This program shows how to use bitwise flags in your programs\n" <<
"sintaxis: programName [-abcdefghi] \n\n" <<
" --optiona | -a : Enable option A (2⁰)\n" <<
" --optionb | -b : Enable option B (2¹)\n" <<
" --optionc | -c : Enable option C (2²)\n" <<
" --optiond | -d : Enable option D (2³)\n" <<
" --optione | -e : Enable option E (2⁴)\n" <<
" --optionf | -f : Enable option F (2⁵)\n" <<
" --optiong | -g : Enable option G (2⁶)\n" <<
" --optioni | -i : Enable option I (2⁷)\n" <<
" --help | -h : Prints this help\n\n";
}
// === FUNCTION ======================================================================
// Name: readArguments
// Description:
// =====================================================================================
static void readArguments ( int argc,char **argv )
{
try
{
for ( ;; )
{
int index;
int c;
#ifdef __linux
c = getopt_long ( argc, argv, short_options, long_options, &index );
#else // ----- not __linux -----
c = getopt (argc, argv, short_options);
#endif // __linux -----
if ( -1 == c )
break;
switch ( c )
{
case 0:
break;
case 'h': // Help
usage ();
exit ( EXIT_SUCCESS );
break;
case 'a':
myoptions |= optiona;
break;
case 'b':
myoptions |= optionb;
break;
case 'c':
myoptions |= optionc;
break;
case 'd':
myoptions |= optiond;
break;
case 'e':
myoptions |= optione;
break;
case 'f':
myoptions |= optionf;
break;
case 'g':
myoptions |= optiong;
break;
case 'i':
myoptions |= optioni;
break;
default:
usage ();
exit ( EXIT_FAILURE );
break;
};
}
}
catch ( std::exception &ex )
{
cout< exit (EXIT_FAILURE);
}
}
I’ve always found very useful the passing of arguments using bit flags. In many of the libraries I’ve used in last years I noted that is common to pass options to functions or methods employing an integer argument (32 bits) and in this way be able to stablish a number of options equal to the number of bits of the data type. Here, you have a very simple example to see how to use bit flags in your C/C++ programs.
// =====================================================================================
//
// Filename: bitflags.cpp
//
// Description: How to use combination of flags in your programs
//
// Version: 1.0
// Created: 24/01/10 10:51:53
// Revision: none
// Compiler: g++
//
// Author: Luis Díaz Más
// Company: http://plagatux.es
//
// =====================================================================================
#include
#include
#include
#include
using namespace std;
// ##### VARIABLES - LOCAL TO THIS SOURCE FILE ################################
static const char short_options [] ="abcdefghi";
#ifdef __linux
static const struct option long_options [] =
{
{ "help", no_argument, NULL, 'h'},
{ "optiona", no_argument, NULL, 'a'},
{ "optionb", no_argument, NULL, 'b'},
{ "optionc", no_argument, NULL, 'c'},
{ "optiond", no_argument, NULL, 'd'},
{ "optione", no_argument, NULL, 'e'},
{ "optionf", no_argument, NULL, 'f'},
{ "optiong", no_argument, NULL, 'g'},
{ "optioni", no_argument, NULL, 'i'},
{ 0, 0, 0, 0 }
};
#endif // __linux -----
enum options {
optiona = 0x01, // 00000001
optionb = 0x02, // 00000010
optionc = 0x04, // 00000100
optiond = 0x08, // 00001000
optione = 0x10, // 00010000
optionf = 0x20, // 00100000
optiong = 0x40, // 01000000
optioni = 0x80, // 10000000
}; // ---------- end of enum options ----------
static unsigned int myoptions=0;
// ##### FUNCTION DEFINITIONS - LOCAL TO THIS SOURCE FILE #####################
static void usage();
static void readArguments ( int argc,char **argv );
// === FUNCTION ======================================================================
// Name: main
// Description:
// =====================================================================================
int main ( int argc, char *argv[] )
{
try
{
readArguments(argc, argv);
cout << "Value of myoptions: " << myoptions << endl;
// Match with only one option
if (myoptions & optiona) cout << "optiona enabled\n";
if (myoptions & optionb) cout << "optionb enabled\n";
if (myoptions & optionc) cout << "optionc enabled\n";
if (myoptions & optiond) cout << "optiond enabled\n";
if (myoptions & optione) cout << "optione enabled\n";
if (myoptions & optionf) cout << "optionf enabled\n";
if (myoptions & optiong) cout << "optiong enabled\n";
if (myoptions & optioni) cout << "optioni enabled\n";
// Match with several options
if (myoptions & (optiona | optionb)) cout << "a + b \n";
if (myoptions & (optiona | optionc)) cout << "a + c \n";
if (myoptions & (optiond | optioni)) cout << "a + c \n";
}
catch (exception &ex)
{
cout << ex.what() << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // ---------- end of function main ----------
// === FUNCTION ======================================================================
// Name: usage
// Description:
// =====================================================================================
static void usage()
{
cout<<"This program shows how to use bitwise flags in your programs\n" <<
"sintaxis: programName [-abcdefghi] \n\n" <<
" --optiona | -a : Enable option A (2⁰)\n" <<
" --optionb | -b : Enable option B (2¹)\n" <<
" --optionc | -c : Enable option C (2²)\n" <<
" --optiond | -d : Enable option D (2³)\n" <<
" --optione | -e : Enable option E (2⁴)\n" <<
" --optionf | -f : Enable option F (2⁵)\n" <<
" --optiong | -g : Enable option G (2⁶)\n" <<
" --optioni | -i : Enable option I (2⁷)\n" <<
" --help | -h : Prints this help\n\n";
}
// === FUNCTION ======================================================================
// Name: readArguments
// Description:
// =====================================================================================
static void readArguments ( int argc,char **argv )
{
try
{
for ( ;; )
{
int index;
int c;
#ifdef __linux
c = getopt_long ( argc, argv, short_options, long_options, &index );
#else // ----- not __linux -----
c = getopt (argc, argv, short_options);
#endif // __linux -----
if ( -1 == c )
break;
switch ( c )
{
case 0:
break;
case 'h': // Help
usage ();
exit ( EXIT_SUCCESS );
break;
case 'a':
myoptions |= optiona;
break;
case 'b':
myoptions |= optionb;
break;
case 'c':
myoptions |= optionc;
break;
case 'd':
myoptions |= optiond;
break;
case 'e':
myoptions |= optione;
break;
case 'f':
myoptions |= optionf;
break;
case 'g':
myoptions |= optiong;
break;
case 'i':
myoptions |= optioni;
break;
default:
usage ();
exit ( EXIT_FAILURE );
break;
};
}
}
catch ( std::exception &ex )
{
cout< exit (EXIT_FAILURE);
}
}
loading...




Últimos comentarios