Inicio > Programación > Bit flags in C/C++

Bit flags in C/C++

Sábado, 20 de agosto de 2011 Dejar un comentario Ir a comentarios

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);
	}
}
GD Star Rating
loading...
Bit flags in C/C++, 10.0 out of 10 based on 1 rating
Share
  1. Sin comentarios aún.
  1. Sin trackbacks aún.