Sabemos que cualquier número que no sea igual a 0
se considera como 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 1
/ 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?
gcc
con-std=c89
y arroja el mismo resultado.Respuestas:
El estándar C define
true
yfalse
como macros en lasstdbool.h
que se expanden1
y0
respectivamente.C11-§7.18:
Para los operadores
==
y!=
, el estándar diceC11-§6.5.9 / 3:
fuente
0 == 0
y0 != 0
etc., no el valor de las macros.true
quiso decir "el valor de una verdadera comparación" o algo, no la macrotrue
ctrl
+f
;)NaN == NaN
es falso yNaN != NaN
es verdadero. No hay ningún problema con esa afirmación.No se indica explícitamente en C11. Todas las operaciones a nivel de idioma devolverán 1 como verdadero (y aceptarán cualquier valor distinto de cero, incluido NaN, como verdadero).
_Bool
, entonces verdadero debe ser 1 porque el estándar solo requiere que tenga 0 y 1. (§6.2.5 / 2).<stdbool.h>
la macro setrue
expande a1
(§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
se expande a 0 o 1 (§6.10.1 / 1)Pero todas las funciones de biblioteca estándar, por ejemplo,
islower
solo 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).fuente
Hay dos áreas del estándar que debe tener en cuenta al tratar con valores booleanos (con lo que me refiero a valores verdaderos / falsos en lugar del
bool/_Bool
tipo C específico ) en C.La primera tiene que ver con el resultado de 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, siempre que una expresión genera un valor booleano, ...Entonces, sí, el resultado de cualquier expresión generadora de booleanos será uno para verdadero o cero para falso. Esto coincide con lo que encontrará
stdbool.h
donde las macros estándartrue
yfalse
se definen de la misma manera.Sin embargo, tenga en cuenta que, siguiendo el principio de robustez de "sea conservador en lo que envíe, liberal en lo que acepte", la interpretación de los números enteros en el contexto booleano es algo más relajada.
Nuevamente, en varias partes de
6.5
, verá un lenguaje como:Por 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é valor se usa 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 (ANSI-C segunda edición y la primera edición) especificó eso, con segmentos de texto como:
Las macros también
stdbool.h
aparecen en C99, pero no en C89 o K&R, ya que ese archivo de encabezado no existía en ese momento.fuente
||
,==
,!=
etc. rendimientoint
, no un tipo booleanoif
,while
,for
, etc, 'verdadero' sólo significa 'no cero'." Esta es la parte sobresaliente de la respuesta y es, en mi opinión, una elección desafortunada de Dennis Ritchie desde hace mucho tiempo. Cualquiera que haya escrito funciones que devuelvan códigos de error como el valor devuelto generalmente lo tiene#define noErr 0
y cualquier código de error distinto de cero es un error. Y luego el problema es la simplicidad y la belleza deif ( ready_to_do_something() ){do_something();}
no funciona. Tiene que serif ( !not_ready_to_do_something() ){do_something();}
"Hay muchas falsedades, pero solo una verdad". VERDADERO debe ser 0.A.7.6/7/10/11
(relacional / igualdad / lógico-y / lógico-o) todos especifican que da 0 o 1 como resultado. Tener una respuesta actualizada para incluir eso.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
if
declaración, C11 6.4.8.1: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
valor de 1 o 0. Por ejemplo, los operadores de igualdad, C11 6.5.9:Todo lo anterior se debe a que C no tenía un tipo booleano hasta el año 1999, e incluso cuando obtuvo uno, las reglas anteriores no se cambiaron. 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 nombra
_Bool
y requiere un compilador moderno. Las cabeceras de lasstdbool.h
macros Definebool
,true
yfalse
, que se expanden para_Bool
,1
y0
respectivamente (para la 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 esta práctica. Es decir:
if(ptr == NULL)
en lugar deif(ptr)
.if((data & mask) != 0)
en lugar deif(data & mask)
.El objetivo de dicho estilo es aumentar la seguridad de los tipos con la ayuda de herramientas de análisis estático, lo que a su vez reduce los errores. Podría decirse que este estilo solo es significativo si usa analizadores estáticos. Aunque en algunos casos conduce a un código autodocumentado más legible, por ejemplo
if(c == '\0')
Bien, la intención es clara, el código se autodocumenta.
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 carácter?fuente
sizeof(bool)
es una implementación específica en C ++. Consulte stackoverflow.com/questions/4897844/is-sizeofbool-defined .if(ptr != NULL)
, o quizásif(!ptr)
?if(c == '\0')
se presta al error de codificación particularmente común de los principiantesif(c = '\0')
, así que lo evito. De acuerdo,if(c)
es malo ... debería ser, por ejemplo,if(valveIsOpen)
He programado en muchos idiomas. He visto que true es 1 o -1 dependiendo del idioma. La lógica detrás del verdadero ser 1 era que un bit era un 0 o un 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 no comparar algo para que sea == verdadero, sino que lo comparo para que sea! = Falso. De esa forma, mi estilo de programación funciona en todos los idiomas. Entonces mi respuesta es no preocuparse por eso, sino programar para que su código funcione correctamente de cualquier manera.
fuente
Esta respuesta debe examinarse 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 contiene es el shell y las reglas para lo que eso significa. Sin embargo, sabe qué son los bits, los que forman un número entero.
1 como un entero se representa libremente en bits, digamos un int de 8 bits con signo 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 con signo de 'entero'. Realmente no puedo decir verdadero, ¿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 son 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 firmar son un poco complicadas y se usaban mucho más comúnmente en el pasado, donde 1 significa verdadero porque es fácil implicar la lógica de que '
Ésa 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 número entero como un booleano, pero el hecho de que la salida sea un número entero no dice nada sobre la operación que realmente se está realizando es bit a bit.
fuente
Ocurrió debido a los operadores relacionales en su
printf
declaración.Operador
==
y operador!=
Dado que
(0 == 0)
es cierto, da un valor1
mientras que,
(0 != 0)
no es así, da un valor0
.fuente