2012-01-08 23 views
9

me preguntaba cómo hacer esto:OR bit a bit (|) en el argumento de la función

func(param1|param2|param3) 

y luego extraer los valores de la función, he visto esto en múltiples funciones, o es mejor hacer esto :

func(param1, ...) 

?

Estoy tratando de hacer esto en C++, y estaba pensando en tener los parámetros para la función como valores en una enumeración.

¿Cómo soluciono esto?

Respuesta

15

Param1, param2, param3 se suelen definir como números con diferentes bits activados. | es un operador de alternativa bit a bit, eso significa que funciona en bits separados.

En el ejemplo:

const int param1 = 0x01; 
const int param2 = 0x02; 
const int param3 = 0x04; 

Cuando se pasa un argumento a la función que realice una alternativa bit a bit de params anteriormente definidos. En función, usted no hace una descomposición, pero comprobar si un bit especificado está activada, el uso de bit a bit conjunción:

void func(int arg){ 
    if(arg & param1) 
    // do something 
    if(arg & param2) 
    // do something else 
    // ... 
} 

func(param1 | param3); 
// "do something" will be done, 
// but "do something else" not. 
+0

También puede definir números como 'int param1and2 = 0x03;' 'que actúan como param1 | param2'; –

+0

Debería señalarse que la restauración de los argumentos '|' hacia atrás solo es posible para patrones de argumentos específicos, como los presentados en la respuesta. De lo contrario, esto no sería posible: '3 | 4' es lo mismo que '1 | 6'. – Vlad

+0

¡Gracias chicos! Esto es lo que terminé haciendo como paxdiablo sugirió – DarkRoast

11

Asumiendo que tiene los valores de los bits independientes (como potencias de dos) como:

#define IS_ON 0x01 
#define IS_LARGE 0x02 
#define IS_RED 0x04 

(o los equivalentes enums o const int valores, dependiendo de lo que quiere hacer ellos - que he usado #define simplemente porque es lo que estoy acostumbrado a), puede pase como:

funcname (IS_ON | IS_RED); // passes in 0x05 

Entonces extraer con algo como:

void funcname (int bitmask) { 
    if ((bitmask & IS_ON) == IS_ON) { // 0x05 & 0x01 -> 0x01 
     // IS_ON bit is set. 
    } 
    : 
} 

Para especificadores de un solo bit, puede salirse con la forma if (bitmask & IS_ON) pero se necesita la verificación completa si sus especificadores pueden ser de varios bits valores (como un nivel de volumen de tres bits de 0 a 7, por ejemplo).

+0

¿Cuál sería la combinación de operadores bit a bit para is_not_on_and_is_not_red? ¿Sería 'funcname (~ IS_ON | ~ IS_RED);'? – ontherocks

+0

explicación clara, pero debe mencionar que los bits deben ser potencias de 2. Correcto ? –

+0

En lugar de las constantes '0x01' puede usar' 1 << 0', '1 << 2',' 1 << 3', etc. Las encuentro más legibles. –

0

Este es un ejemplo útil de cómo crear la función "cuadro de mensaje" con tipos de botones arbitrarias:

enum Button 
{ 
    OK =  0x0001, 
    CANCEL = 0x0010, 
    YES =  0x0100, 
    NO =  0x1000 
}; 

void messagebox(char *text, int button) 
{ 
    char msg[256]; 
    strcpy(msg, text); 

    if ((button & Button::OK) == Button::OK) 
     strcat(msg, " [OK]"); 
    if ((button & Button::CANCEL) == Button::CANCEL) 
     strcat(msg, " [Cancel]"); 
    if ((button & Button::YES) == Button::YES) 
     strcat(msg, " [Yes]"); 
    if ((button & Button::NO) == Button::NO) 
     strcat(msg, " [No]"); 

    cout << msg << endl; 
} 

int main() 
{ 
    messagebox("salam", Button::OK | Button::CANCEL); 
    return 0; 
}