verdad valor una tablas tabla proposiciones proposicion operadores logicos las hacer explicacion ejemplos determinar compuestas como c

una - ¿El estándar C indica explícitamente el valor de verdad como 0 o 1?



valor de verdad de las proposiciones compuestas (7)

¿El estándar C indica explícitamente los valores de true de true y false como 0 y 1 respectivamente?

El estándar C define true y false como macros en stdbool.h que se expanden a 1 y 0 respectivamente.

C11-§7.18:

Las tres macros restantes son adecuadas para su uso en #if directivas de preprocesamiento. Son

true

que se expande a la constante entera 1 ,

false

que se expande a la constante entera 0 [...]

En cuanto a los operadores == y !=

C11-§6.5.9 / 3:

Los operadores == (igual a) y != (No igual a) son análogos a los operadores relacionales, excepto por su precedencia más baja. 108) Cada uno de los operadores produce 1 si la relación especificada es verdadera y 0 si es falsa. El resultado tiene tipo int . Para cualquier par de operandos, exactamente una de las relaciones es verdadera.

Sabemos que cualquier número que no sea igual a 0 se considera true en C, por lo que podemos escribir:

int a = 16; while (a--) printf("%d/n", a); // prints numbers from 15 to 0

Sin embargo, me preguntaba si verdadero / falso se define como 0 en C, así que probé el siguiente código:

printf("True = %d, False = %d/n", (0 == 0), (0 != 0)); // prints: True = 1, False = 0

¿El estándar C indica explícitamente los valores de verdad de verdadero y falso como 1 y 0 respectivamente?


Está mezclando muchas cosas diferentes: declaraciones de control, operadores y tipos booleanos. Cada uno tiene sus propias reglas.

Las declaraciones de control funcionan como, por ejemplo, la declaración if , C11 6.4.8.1:

En ambas formas, la primera subestimación se ejecuta si la expresión se compara desigual a 0.

while for etc tienen la misma regla. Esto no tiene nada que ver con "verdadero" o "falso".

En cuanto a los operadores que supuestamente están produciendo un resultado booleano, en realidad están produciendo un int con valor 1 o 0. Por ejemplo, los operadores de igualdad, C11 6.5.9:

Cada uno de los operadores produce 1 si la relación especificada es verdadera y 0 si es falsa

Todo lo anterior se debe a que C no tenía un tipo booleano hasta el año 1999, e incluso cuando lo obtuvo, las reglas anteriores no se modificaron. Entonces, a diferencia de la mayoría de los otros lenguajes de programación donde las declaraciones y los operadores producen un tipo booleano (como C ++ y Java), solo producen un int , con un valor cero o no cero. Por ejemplo, sizeof(1==1) dará 4 en C pero 1 en C ++.

El tipo booleano real en C se llama _Bool y requiere un compilador moderno. El encabezado stdbool.h define macros bool , true y false , que se expanden a _Bool , 1 y 0 respectivamente (para compatibilidad con C ++).

Sin embargo, se considera una buena práctica de programación tratar las declaraciones de control y los operadores como si realmente requirieran / produjeran un tipo booleano. Ciertos estándares de codificación como MISRA-C recomiendan dicha práctica. Es decir:

if(ptr == NULL) lugar de if(ptr) .

if((data & mask) != 0) lugar de if(data & mask) .

El objetivo de este estilo es aumentar la seguridad de los tipos con la ayuda de herramientas de análisis estático, que a su vez reduce los errores. Podría decirse que este estilo solo es significativo si utiliza analizadores estáticos. Aunque en algunos casos conduce a un código más fácil de documentar, por ejemplo

if(c == ''/0'')

Bien, la intención es clara, el código se documenta por sí mismo.

versus

if(c)

Malo. Podría significar cualquier cosa, y tenemos que buscar el tipo de c para entender el código. ¿Es un número entero, un puntero o un personaje?


Esta respuesta debe analizarse un poco más de cerca.

La definición real en C ++ es que todo lo que no sea 0 se trata como verdadero. ¿Por qué es esto relevante? Debido a que C ++ no sabe qué es un número entero por cómo lo pensamos: creamos ese significado, todo lo que tiene es el caparazón y las reglas de lo que eso significa. Sin embargo, sabe qué bits son, lo que constituye un número entero.

1 como número entero se representa libremente en bits, digamos un int con signo de 8 bits como 0000 0001. Muchas veces lo que vemos visualmente es una mentira, -1 es una forma mucho más común de representarlo debido a la naturaleza firmada de ''entero''. Realmente no puedo decir verdad, ¿por qué? Porque su operación NO es 1111 1110. Ese es un problema realmente importante para un booleano. Cuando hablamos de un booleano, es solo 1 bit: es realmente simple, 0 es falso y 1 es verdadero. Todas las operaciones lógicas se consideran triviales. Es por eso que ''-1'' debe designarse como ''verdadero'' para enteros (con signo). 1111 1111 NOT''ed se convierte en 0000 0000 --- la lógica se mantiene y estamos bien. Las entradas sin signo son un poco complicadas y se usaban mucho más en el pasado, donde 1 significa verdadero porque es fácil implicar la lógica de que ''cualquier cosa que no sea 0 es verdadera''.

Esa es la explicación. Digo que la respuesta aceptada aquí es incorrecta: no hay una definición clara en la definición de C / C ++. Un booleano es un booleano, puede tratar un entero como un booleano, pero el hecho de que la salida sea un entero no dice nada acerca de la operación que se está haciendo en realidad.


Hay dos áreas del estándar que debe tener en cuenta al tratar con valores booleanos (con los cuales quiero decir valores verdaderos / falsos en lugar del tipo específico C bool/_Bool ) en C.

El primero tiene que ver con el resultado de las expresiones y se puede encontrar en varias partes de C11 6.5 Expressions (operadores relacionales y de igualdad, por ejemplo). La conclusión es que, cada vez que una expresión genera un valor booleano, ...

... produce 1 si la relación especificada es verdadera y 0 si es falsa. El resultado tiene el tipo int.

Entonces, sí, el resultado de cualquier expresión booleana que genere será uno para verdadero o cero para falso. Esto coincide con lo que encontrará en stdbool.h donde las macros estándar true y false se definen de la misma manera.

Sin embargo, tenga en cuenta que, siguiendo el principio de robustez de "ser conservador en lo que envía, liberal en lo que acepta", la interpretación de los enteros en el contexto booleano es algo más relajada.

Nuevamente, desde varias partes de 6.5 , verá un lenguaje como:

El || el operador producirá 1 si alguno de sus operandos se compara desigual a 0; de lo contrario, produce 0. El resultado tiene el tipo int.

A partir de eso (y otras partes), es obvio que cero se considera falso y cualquier otro valor es verdadero.

Por otro lado, el lenguaje que especifica qué valores se usan para la generación e interpretación booleana también aparece en C99 y C89, por lo que han existido durante bastante tiempo. Incluso K&R (segunda edición de ANSI-C y la primera edición) especificó eso, con segmentos de texto como:

Expresiones relacionales como i > j y expresiones lógicas conectadas por && y || se definen para tener el valor 1 si es verdadero y 0 si es falso.

En la parte de prueba de if , while , for , etc., "verdadero" solo significa "distinto de cero".

El operador && ... devuelve 1 si sus dos operandos se comparan desigualmente con cero, 0 de lo contrario.

El || operador ... devuelve 1 si cualquiera de sus operandos se compara desigual a cero, y 0 en caso contrario.

Las macros en stdbool.h aparecen en C99, pero no en C89 o K&R ya que ese archivo de encabezado no existía en ese momento.


He programado en muchos idiomas. He visto verdadero ser 1 o -1 dependiendo del idioma. La lógica detrás del verdadero ser 1 era que un bit era 0 o 1. La lógica detrás del verdadero ser -1 era que el! El operador era el complemento de uno. Cambió todos los 1 a 0 y todos los 0 a 1 en un int. Entonces, para un int,! 0 = -1 y! (- 1) = 0. Esto me ha hecho tropezar lo suficiente como para que no compare algo como == verdadero, sino que lo compare como falso =. De esa manera, mi estilo de programación funciona en todos los idiomas. Entonces, mi respuesta es no preocuparme por eso, sino programar para que su código funcione correctamente de cualquier manera.


No se indica explícitamente en C11. Todas las operaciones a nivel de lenguaje devolverán 1 como verdadero (y aceptarán cualquier valor distinto de cero, incluido NaN, como verdadero).

  • Si le preocupa _Bool , true debe ser 1 porque el estándar solo requiere que contenga 0 y 1. (§6.2.5 / 2).
  • También en <stdbool.h> la macro true expande a 1 (§7.18 / 3)
  • == ,! != , < , > , <= y >= devolver 0 o 1 (§6.5.8 / 6, §6.5.9 / 3).
  • ! , && y || devuelve 0 o 1 (§6.5.3.3 / 5, §6.5.13 / 3, §6.5.14 / 3)
  • defined expande a 0 o 1 (§6.10.1 / 1)

Pero todas las funciones estándar de la biblioteca, por ejemplo, islower simplemente dicen "distinto de cero" para la verdad (por ejemplo, §7.4.1 / 1, §7.17.5.1 / 3, §7.30.2.1 / 1, §7.30.2.2.1 / 4).

§6.2.5 / 2 : Un objeto declarado como tipo _Bool es lo suficientemente grande como para almacenar los valores 0 y 1.

§6.5.5.3 / 5 : ¡El resultado del operador de negación lógica ! es 0 si el valor de su operando se compara desigual a 0, 1 si el valor de su operando se compara igual a 0. ...

§6.5.8 / 6 : Cada uno de los operadores < (menor que), > (mayor que), <= (menor o igual que) y >= (mayor o igual que) producirá 1 si la relación especificada es verdadero y 0 si es falso. 107) ...

§6.5.9 / 3 : Los operadores == (igual a) y != (No igual a) son análogos a los operadores relacionales, excepto por su precedencia más baja.108) Cada uno de los operadores produce 1 si la relación especificada es verdadera y 0 si es falso. ...

§6.5.13 / 3 : El operador && producirá 1 si sus dos operandos se comparan desigualmente con 0; ...

§6.5.14 / 3 : El || el operador producirá 1 si alguno de sus operandos se compara desigual a 0; ...

§6.10.1 / 1 : ... puede contener expresiones de operador unario de la forma - defined identifier - o - defined ( identifier ) - que evalúan a 1 si ...

§7.4.1 (Funciones de clasificación de caracteres) / 1 : Las funciones de esta subcláusula devuelven distinto de cero (verdadero) si y solo si ...

§7.18 / 3 : Las tres macros restantes son adecuadas para usar en #if directivas de preprocesamiento. Son - true - que se expanden a la constante entera 1, ...

§7.17.5.1 / 3 : La función genérica atomic_is_lock_free devuelve distinto de cero (verdadero) si y solo si las operaciones del objeto están libres de bloqueo. ...

§7.30.2.1 (Funciones de clasificación de caracteres anchos) / 1 : Las funciones en esta subcláusula devuelven distinto de cero (verdadero) si y solo si ...

§7.30.2.2.1 / 4 : La función iswctype devuelve distinto de cero (verdadero) si y solo si ...


Sucedió debido a los operadores relacionales en su declaración printf .

Operador == y operador !=

Como (0 == 0) es verdadero, da un valor 1

mientras que (0 != 0) no es cierto, entonces da un valor 0 .