varias poner operator graficos graficas como and c expression

c - poner - Usando if(!!(expr)) en lugar de if(expr)



or operator (5)

OP está mirando un viejo modismo de codificación, lo que tenía sentido BITD (retroceso en el día).

  1. Un uso primario de !! fue manejar implementaciones de C que convirtieron la expresión en un if(expr) a int lugar de probar contra cero.

Considere lo que sucede cuando expr se convierte a int y luego se prueba contra 0. (Desde C89, esto no es conforme, ya que la prueba debería ser una prueba directa contra 0)

int i; long li; double d; // no problems if (i & 5) ... if (d > 4.0) ... // problems if (li & 0x10000) ... (Hint: int is 16-bit) if (d) (d might have a value outside `int` range. // fix if (!!(li & 0x10000)) if (!!d)

¡Así que en pre C89 cumplidores y C89 no conforme y más adelante, usando !! frente a esa debilidad. Algunos viejos hábitos tardan mucho en morir.

  1. A principios de C ++ , no había tipo bool . ¡¡Entonces el código que quería probar la confianza necesaria para usar el !! idioma

    class uint256; // Very wide integer uint256 x; // problem as (int)x may return just the lower bits of x if (x) // fix if (!!x)

  2. ¿Qué sucede con C ++ hoy? (Sé que esta es una pregunta C) cuando no hay un operador (bool) definido, ¿no se utiliza el operador (int) ? Esto da como resultado el mismo problema que el n. ° 2. Al igual que durante muchos años, las bases de códigos C y C ++ se mantuvieron sincronizadas, !! usando !! tuvo relevancia con construcciones como if (!!x) .

Usando !! funciona hoy pero ciertamente ha caído en desgracia ya que resuelve el problema que ya no ocurre con una frecuencia significativa.

Mientras leía el código de ejemplo proporcionado por Texas Instruments para su SensorTag me encontré con el siguiente fragmento.

void SensorTagIO_processCharChangeEvt(uint8_t paramID) { ... if (!!(ioValue & IO_DATA_LED1)) { PIN_setOutputValue(hGpioPin, Board_LED1, Board_LED_ON); } else { PIN_setOutputValue(hGpioPin, Board_LED1, Board_LED_OFF); } if (!!(ioValue & IO_DATA_LED2)) { PIN_setOutputValue(hGpioPin, Board_LED2, Board_LED_ON); } else { PIN_setOutputValue(hGpioPin, Board_LED2, Board_LED_OFF); } if (!!((ioValue & IO_DATA_BUZZER))) { Clock_start(buzzClockHandle); } ... }

La declaración es así (en el mismo archivo).

#define IO_DATA_LED1 0x01 static uint8_t ioValue;

¿ if (!!(ioValue & IO_DATA_LED1)) ofrece alguna ventaja sobre if (ioValue & IO_DATA_LED1) ?


Aunque silenciar la advertencia del compilador para el bit-sabio & es lo más probable, parece que también podría ser el resultado de una refactorización para agregar enumeraciones para facilitar la lectura desde:

PIN_setOutputValue(int,int,bool); //function definition PIN_setOutputValue(hGpioPin, Board_LED1,!!(ioValue & IO_DATA_LED1)); PIN_setOutputValue(hGpioPin, Board_LED2,!!(ioValue & IO_DATA_LED2)); //note: the !! is necessary here in case sizeof ioValue > sizeof bool //otherwise it may only catch the 1st 8 LED statuses as @M.M points out

a:

enum led_enum { Board_LED_OFF = false, Board_LED_ON = true }; PIN_setOutputValue(int,int,bool); //function definition //... PIN_setOutputValue(hGpioPin, Board_LED1,!!(ioValue & IO_DATA_LED1)?Board_LED_ON:Board_LED_OFF); PIN_setOutputValue(hGpioPin, Board_LED2,!!(ioValue & IO_DATA_LED2)?Board_LED_ON:Board_LED_OFF);

Como eso excedió el límite de 80 caracteres, se refactorizó a

if (!!(ioValue & IO_DATA_LED1)) { PIN_setOutputValue(hGpioPin, Board_LED1, Board_LED_ON); } else { PIN_setOutputValue(hGpioPin, Board_LED1, Board_LED_OFF); } if (!!(ioValue & IO_DATA_LED2)) { PIN_setOutputValue(hGpioPin, Board_LED2, Board_LED_ON); } else { PIN_setOutputValue(hGpioPin, Board_LED2, Board_LED_OFF); }

Personalmente, hubiera preferido la versión inicial por legibilidad, pero esta versión es común cuando las líneas de código se usan como métrica (me sorprende que no declarara variables para cada estado, establezca cada estado por separado y luego use eso).

La siguiente versión de este código de "Mejor práctica" podría verse así:

bool boardled1State; bool boardled2State; //... boardled1State = !!(ioValue & IO_DATA_LED1); boardled2State = !!(ioValue & IO_DATA_LED2); //... if (boardled1State) { PIN_setOutputValue(hGpioPin, Board_LED1, Board_LED_ON); } else { PIN_setOutputValue(hGpioPin, Board_LED1, Board_LED_OFF); } if (boardled2State) { PIN_setOutputValue(hGpioPin, Board_LED2, Board_LED_ON); } else { PIN_setOutputValue(hGpioPin, Board_LED2, Board_LED_OFF); } //... and so on

Todo eso podría haberse hecho así:

for (int i=0;i<numleds;i++) PIN_setOutputValue(hGpioPin, i ,!!(ioValue & (1<<i)));


En MSVC, la conversión de un entero a un bool implícitamente en una instrucción if puede generar una advertencia. Haciéndolo a través de !! no. Advertencia similar puede existir en otros compiladores.

¡Supongamos que el código se compiló con esa advertencia habilitada, y una decisión de tratar todas las advertencias como errores, usando !! es una forma breve y portátil de decir "sí, quiero que este entero sea un bool ".


La aplicación del operador lógico not ( ! ) Dos veces tiene el propósito de normalizar un valor para que sea 0 o 1. En una expresión de control de una instrucción if, eso no hace ninguna diferencia. La instrucción if solo se preocupa por el valor cero o distinto de cero, ¡el pequeño !! La danza es completamente inútil.

Algunas guías de estilo de codificación pueden exigir este tipo de baile, lo que podría ser la razón por la cual el código TI que publicaste lo hace. Sin embargo, no he visto ninguno que lo haga.


La expresión !!x , o !(!x) , significa 1 si x es un valor verdadero (un número distinto de cero o un puntero no nulo), de lo contrario 0. ¡Es equivalente a x != 0 , y es casi lo mismo que C99 (_Bool)x pero disponible en compiladores anteriores a C99 o cuyos desarrolladores han optado por no implementar C99 (como cc65 que se dirige a MOS 6502).

El condicional en su conjunto es equivalente a lo siguiente:

if (ioValue & IO_DATA_LED1) { /* what to do if the IO_DATA_LED1 bit is true */ } else { /* what to do if the IO_DATA_LED1 bit is false */ }

En C, significa "si el AND bit a bit de esos dos valores no es cero, ejecute el bloque".

Pero algunas guías de estilo de codificación pueden prohibir un AND ( & ) bit a nivel superior en la condición de una instrucción if , suponiendo que sea un error tipográfico para el AND lógico ( && ). Está en la misma clase de errores que usar = (asignación) en lugar de == (comparación de igualdad), para lo cual muchos compiladores ofrecen un diagnóstico. Las opciones de advertencia de GCC describen diagnósticos como estos:

-Wlogical-op : -Wlogical-op sobre usos sospechosos de operadores lógicos en expresiones. Esto incluye el uso de operadores lógicos en contextos en los que es probable que se espere un operador de bits.

-Wparentheses : -Wparentheses si los paréntesis se omiten en ciertos contextos, como cuando hay una asignación en un contexto donde se espera un valor de verdad

El uso de una paráfrasis como (a & B) != 0 , (_Bool)(a & B) , o !!(a & B) comunica al compilador y a otros desarrolladores que el uso de un operador bit a bit fue intencional.

Vea también una respuesta relacionada sobre !!x en JavaScript .