Extrañas definiciones de macros VERDADERO y FALSO

6 minutos de lectura

avatar de usuario
Keshava GN

He visto las siguientes definiciones de macros en un libro de codificación.

#define TRUE  "https://stackoverflow.com/"/"https://stackoverflow.com/"
#define FALSE '-'-'-'

No había ninguna explicación allí.

Por favor, explícame cómo funcionarán estos TRUE y FALSE.

  • Creo que es una forma divertida de definir VERDADERO como 1 y FALSO como 0

    – Enano negro

    3 de diciembre de 2015 a las 9:47

  • Tenga en cuenta que esta es una idea terrible sin corchetes alrededor de esas expresiones. Quiero decir que es una idea terrible con ellos, pero sin usted solo está pidiendo una larga noche de depuración.

    – TartánLlama

    3 de diciembre de 2015 a las 9:51


  • ¿Puedo saber el libro de codificación al que hace referencia?

    – artm

    3 de diciembre de 2015 a las 9:54

  • Espero que ese libro haya incluido esto como un ejemplo de código malo o deliberadamente oscuro.

    – Jon Hanna

    3 de diciembre de 2015 a las 10:13

  • @Daniel: Otra idea sería rand()%2 definir QUIZÁS como rand()%2, por lo que a veces es == VERDADERO ya veces == FALSO.

    – Kaiserludi

    3 de diciembre de 2015 a las 15:24

avatar de usuario
Arrendajo

Vamos a ver: "https://stackoverflow.com/" / "https://stackoverflow.com/" significa el char literal /dividido por el char literal "https://stackoverflow.com/" sí mismo. El resultado es uno, que suena razonable para TRUE.

Y '-' - '-' significa el char literal '-', sustraído de sí mismo. Esto es cero (FALSE).

Hay dos problemas con esto: primero, no es legible. Usando 1 y 0 es absolutamente mejor. Además, como han señalado TartanLlama y KerrekSB, si alguna vez va a usar esa definición, agregue paréntesis alrededor de ellos para que no tenga sorpresas:

#include <stdio.h>

#define TRUE  "https://stackoverflow.com/"/"https://stackoverflow.com/"
#define FALSE '-'-'-'

int main() {
        printf ("%d\n", 2 * FALSE);
        return 0;
}

Esto imprimirá el valor de la char literal '-' (45 en mi sistema).

Con paréntesis:

#define TRUE  ("https://stackoverflow.com/"/"https://stackoverflow.com/")
#define FALSE ('-'-'-')

el programa imprime correctamente cero, aunque no tiene mucho sentido multiplicar un valor real por un número entero, pero es solo un ejemplo del tipo de errores inesperados que podrían afectarlo si no coloca entre paréntesis sus macros.

  • En realidad, tiene sentido multiplicar con el valor de verdad. Por ejemplo, la sangría*should_indent dará como resultado 0 o una sangría basada en si should_indent sin bifurcación. (Supongo que este es un mal ejemplo, cuando se trabaja con bifurcación simple de texto no importa, (he visto esta técnica en sombreadores y en XPATH (ambos son demasiado diferentes y no recuerdo la forma exacta)))

    – Alpedar

    4 de diciembre de 2015 a las 9:02

  • Alpedar, pero no conceptualmente y matemáticamente tiene sentido hacerlo; en este caso, sería más claro (y conceptualmente tendría sentido) usar un if en lugar de multiplicar TRUE por un entero.

    – Jay

    4 de diciembre de 2015 a las 10:26


  • La negación lógica podría implementarse como notx = TRUE- x; y funciona bien Excepto eso TRUE-FALSE es -44 (asumiendo ASCII)

    –Hagen von Eitzen

    5 de diciembre de 2015 a las 9:43

  • @MarcWittke: Bueno, las personas que abusan del preprocesador C con macros rotas como estas pronto se quedarán sin amigos. Es bien sabido que la simple sustitución de texto de cosas que no están rigurosamente protegidas con paréntesis puede crear roturas extremadamente no obvias, razón por la cual C++ presenta tantas formas de hacer las cosas. sin que el preprocesador C, como plantillas y static const bool TRUE = true;. (Aunque esta definición en realidad tiene un tipo de intno bool.)

    – Peter Cordes

    30 de mayo de 2019 a las 11:22

avatar de usuario
Enano negro

Es solo otra forma de escribir.

#define TRUE 1
#define FALSE 0

La expresion "https://stackoverflow.com/"/"https://stackoverflow.com/" dividirá el valor de char de "https://stackoverflow.com/" por sí mismo, lo que dará como resultado 1.

La expresion '-'-'-' restará el valor char de '-' de sí mismo, lo que dará como resultado 0.

Soportes alrededor del conjunto define sin embargo, faltan expresiones, lo que puede provocar errores en el código que utiliza estas macros. La respuesta de Jay lo aborda bastante bien.

Un ejemplo de escenario de la “vida real” en el que olvidar los corchetes puede ser perjudicial es el uso combinado de estas macros con un operador de conversión de estilo C. Si alguien decide lanzar estas expresiones a bool en C++ por ejemplo:

#include <iostream>

#define TRUE  "https://stackoverflow.com/"/"https://stackoverflow.com/"
#define FALSE '-'-'-'

int main() {
    std::cout << "True: " << (bool) TRUE << std::endl;
    std::cout << "False: " << (bool) FALSE << std::endl;
    return 0;
}

Esto es lo que obtenemos:

True: 0
False: -44

Asi que (bool) TRUE en realidad evaluaría a falsey (bool) FALSE evaluaría a true.

avatar de usuario
Latif sufí

es equivalente a escribir

#define TRUE 1
#define FALSE 0

cual es la expresion "https://stackoverflow.com/"/"https://stackoverflow.com/" en realidad lo que hace es dividir al personaje / (cualquiera que sea su valor numérico) por sí mismo, por lo que se convierte en 1.

Del mismo modo, la expresión '-'-'-' resta el caracter - de sí mismo y se evalúa como 0.

seria mejor escribir

#define TRUE ("https://stackoverflow.com/"/"https://stackoverflow.com/")
#define FALSE ('-'-'-')

para evitar cambios accidentales de valores cuando se usa con otros operadores de mayor precedencia.

avatar de usuario
ouah

Jay ya respondió por qué los valores de estas expresiones son 0 y 1.

Por el bien de la historia, estas expresiones "https://stackoverflow.com/"/"https://stackoverflow.com/" y '-'-'-' provienen de una de las entradas de 1er Concurso Internacional de Código C Ofuscado en 1984:

int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n","https://stackoverflow.com/"/"https://stackoverflow.com/"));}read(j,i,p){write(j/p+p,i---j,i/i);}

(Enlace al programa aquíhay una pista de lo que hace este programa en la página IOCCC anterior).

Además, si recuerdo correctamente estas expresiones como macros ofuscadas para TRUE y FALSE también fueron cubiertos en el libro “Obfuscated C and Other Mysteries” de Don Libes (1993).

avatar de usuario
anand

Es una forma divertida de escribir macros para True y False.

Como se han dado muchas explicaciones / significa un número de 1 byte (según ASCII) cuando se divide por sí mismo te da 1 que será tratado como True y de la misma manera - es nuevamente un número de byte cuando se resta el mismo valor que le da 0 que se interpretará como false

#define TRUE  "https://stackoverflow.com/"/"https://stackoverflow.com/"
#define FALSE '-'-'-'

por lo tanto podemos reemplazar / o - con cualquier char que nos guste, por ejemplo:

#define TRUE  '!"https://stackoverflow.com/"!'
#define FALSE 'o'-'o'

Mantendrá el mismo significado que la expresión original.

avatar de usuario
Fabien

Comencemos con la verdad. Puedes leerlo como "https://stackoverflow.com/" / "https://stackoverflow.com/", que significa “carácter “https://stackoverflow.com/” dividido por el carácter “https://stackoverflow.com/””. Dado que cada carácter, en C, es un valor numérico (en un byte), se puede leer como “el valor ASCII del carácter “https://stackoverflow.com/” dividido por el valor ASCII de ese mismo carácter”, que significa 1 (porque, obviamente, x/x es 1). Por eso, TRUE es 1

Para FALSEes el mismo razonamiento: '-'-'-' lee '-' - '-'es decir, “el valor ASCII de ‘-‘ menos el valor ASCII de ‘-‘”, que es 0. Por lo tanto, FALSE es 0

Esta es una forma desagradable de decir lo obvio.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad