Eu acho que é apenas uma maneira engraçada para definir VERDADEIRO como 1 e FALSO como 0
BlackDwarf
160
Observe que essa é uma péssima idéia sem colchetes em torno dessas expressões. Quero dizer, é uma péssima ideia para eles, mas sem você está apenas pedindo uma longa noite de depuração.
TartanLlama
70
Posso saber o livro de codificação que você está referenciando?
Art
47
Espero que o livro inclua isso como um exemplo de código ruim ou deliberadamente obscuro.
Jon Hanna
31
@ Daniel: Outra idéia seria rand ()% 2 definir TALVEZ como rand ()% 2, de modo que às vezes é == VERDADEIRO e às vezes == FALSO.
Kaiserludi
Respostas:
380
Vamos ver: '/' / '/'significa o charliteral /, dividido pelo próprio charliteral '/'. O resultado é um, que parece razoável TRUE.
E '-' - '-'significa o charliteral '-', subtraído de si mesmo. Isso é zero ( FALSE).
Existem dois problemas com isso: primeiro, não é legível. Usando 1e 0é absolutamente melhor. Além disso, como o TartanLlama e o KerrekSB apontaram, se você alguma vez usar essa definição, adicione parênteses em torno deles para não ter surpresas:
Isso imprimirá o valor do charliteral '-'(45 no meu sistema).
Entre parênteses:
#define TRUE ('/'/'/')#define FALSE ('-'-'-')
o programa imprime corretamente zero, mesmo que não faça muito sentido multiplicar um valor de verdade por um número inteiro, mas é apenas um exemplo do tipo de bugs inesperados que poderiam mordê-lo se você não colocar parênteses suas macros.
Droga Eu tomei um monte de compreendê-lo: é ainda pensei que era uma coisa estranha como glifos ... não sei xD
Luis Masuelli
8
Na verdade, faz sentido multiplicar com o valor da verdade. Para o recuo do exame * should_indent resultará em 0 ou recuo, com base em se deveria_indent sem ramificação. (Acho que esse é um mau exemplo, ao trabalhar com ramificação única de texto não importa, (vi essa técnica em shaders e no XPATH (ambos muito diferentes e não me lembro da forma exata))
Alpedar
2
Alpedar - mas não conceitualmente e matematicamente faz sentido fazer isso - nesse caso, seria mais claro (e conceitualmente faz sentido) usar um em ifvez de multiplicar TRUEpor um número inteiro.
Jay
4
Ótima explicação. Tenha um crachá de ouro!
Michael Hampton
2
A negação lógica pode ser implementada notx = TRUE- x;e funciona bem. Excepto que TRUE-FALSEé -44 (ASCII assumindo)
Hagen von Eitzen
89
É apenas outra maneira de escrever
#define TRUE 1#define FALSE 0
A expressão '/'/'/'dividirá o valor do caractere '/'por si só, o que fornecerá 1 como resultado.
A expressão '-'-'-'subtrairá o valor de char de '-'si mesmo, o que fornecerá 0 como resultado.
No defineentanto, faltam colchetes em torno das expressões inteiras , o que pode levar a erros no código usando essas macros. A resposta de Jay aborda isso muito bem.
Um exemplo de cenário "real" em que esquecer os colchetes pode ser prejudicial é o uso combinado dessas macros com um operador de conversão no estilo C. Se alguém decidir converter essas expressões boolno C ++, por exemplo:
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
(Link para o programa aqui , há uma dica do que esse programa faz na página da IOCCC acima.)
Além disso, se eu me lembro corretamente dessas expressões como macros ofuscadas TRUEe FALSEtambém foram abordadas no livro "Obfuscated C and Other Mysteries" de Don Libes (1993).
É uma maneira hilária de escrever macros para TrueeFalse .
Como muitas explicações foram fornecidas /, um número de 1 byte (conforme ASCII), quando dividido por si só, fornece a você o 1que será tratado Truee, da mesma forma, -é novamente um número de byte ao subtrair o mesmo valor 0que será interpretado comofalse
#define TRUE '/'/'/'#define FALSE '-'-'-'
portanto, podemos substituir /ou -por qualquer caractere que desejarmos, por exemplo:
#define TRUE '!'/'!'#define FALSE 'o'-'o'
Manterá o mesmo significado que a expressão original.
Vamos começar com true. Você pode lê-lo como '/' / '/', o que significa "caractere '/' dividido pelo caractere '/'". Como cada caractere, em C, é um valor numérico (em um byte), ele pode ser lido como "o valor ASCII do caractere '/' dividido pelo valor ASCII desse mesmo caractere", o que significa 1 (porque, obviamente, x / x é 1). Conseqüentemente,TRUE é 1.
Pois FALSE, é o mesmo raciocínio: '-'-'-'lê '-' - '-', ie "o valor ASCII de '-' menos o valor ASCII de '-'", que é 0. Portanto, FALSEé 0.
Esta é uma maneira desagradável de afirmar o óbvio.
@Fabien: Não depende de ASCII. '/'/'/'é 1 para qualquer conjunto de caracteres válido, seja '/' == 47(como em ASCII) ou '/' == 97(como em EBCDIC) ou qualquer outro valor.
Keith Thompson
4
@Pawel: Uma implementação conforme C não pode mapear '/'a 0. Esse valor é reservado para o caractere nulo.
Keith Thompson
2
Você está sendo pedante.
precisa saber é o seguinte
3
@ Matheus208 Se Pawel estava sendo pedante, então isso é ('-'-'-'), já que seu argumento foi baseado em uma condição não declarada; descrever os comentários de Keith como pedantes pode ser mais ('/' / '/'), mas eu os chamaria de "esclarecedor" (e com os smileys adicionados "pedante" definitivamente me parece '/' - '/'). Pode ser ('-' / '-') que os comentários juntos possam ser chamados de pedantes, mas, 1) isso não é algo obrigatório nesse campo? 2) eles me fizeram pensar; e 3) sou um pouco mais claro em algumas coisas do que era. E sim, acho que estou sendo pedante! (Mas eu sou mais claro sobre o que "pedante" significa do que eu era! ;-) #
Respostas:
Vamos ver:
'/' / '/'
significa ochar
literal/
, dividido pelo própriochar
literal'/'
. O resultado é um, que parece razoávelTRUE
.E
'-' - '-'
significa ochar
literal'-'
, subtraído de si mesmo. Isso é zero (FALSE
).Existem dois problemas com isso: primeiro, não é legível. Usando
1
e0
é absolutamente melhor. Além disso, como o TartanLlama e o KerrekSB apontaram, se você alguma vez usar essa definição, adicione parênteses em torno deles para não ter surpresas:Isso imprimirá o valor do
char
literal'-'
(45 no meu sistema).Entre parênteses:
o programa imprime corretamente zero, mesmo que não faça muito sentido multiplicar um valor de verdade por um número inteiro, mas é apenas um exemplo do tipo de bugs inesperados que poderiam mordê-lo se você não colocar parênteses suas macros.
fonte
if
vez de multiplicarTRUE
por um número inteiro.notx = TRUE- x;
e funciona bem. Excepto queTRUE-FALSE
é -44 (ASCII assumindo)É apenas outra maneira de escrever
A expressão
'/'/'/'
dividirá o valor do caractere'/'
por si só, o que fornecerá 1 como resultado.A expressão
'-'-'-'
subtrairá o valor de char de'-'
si mesmo, o que fornecerá 0 como resultado.No
define
entanto, faltam colchetes em torno das expressões inteiras , o que pode levar a erros no código usando essas macros. A resposta de Jay aborda isso muito bem.Um exemplo de cenário "real" em que esquecer os colchetes pode ser prejudicial é o uso combinado dessas macros com um operador de conversão no estilo C. Se alguém decidir converter essas expressões
bool
no C ++, por exemplo:Aqui está o que temos:
Então,
(bool) TRUE
seria realmente avaliarfalse
e(bool) FALSE
avaliartrue
.fonte
É equivalente a escrever
O que a expressão
'/'/'/'
realmente faz é dividir o caractere/
(qualquer que seja seu valor numérico) por si mesmo, para que ele se torne1
.Da mesma forma, a expressão
'-'-'-'
subtrai o caractere-
de si e avalia como0
.Seria melhor escrever
para evitar alterações acidentais de valores quando usadas com outros operadores de alta precedência.
fonte
Jay já respondeu por que os valores dessas expressões são
0
e1
.Para a história bem, estas expressões
'/'/'/'
e'-'-'-'
vêm de uma das entradas de Concurso código ofuscado C 1st International, em 1984 :(Link para o programa aqui , há uma dica do que esse programa faz na página da IOCCC acima.)
Além disso, se eu me lembro corretamente dessas expressões como macros ofuscadas
TRUE
eFALSE
também foram abordadas no livro "Obfuscated C and Other Mysteries" de Don Libes (1993).fonte
É uma maneira hilária de escrever macros para
True
eFalse
.Como muitas explicações foram fornecidas
/
, um número de 1 byte (conforme ASCII), quando dividido por si só, fornece a você o1
que será tratadoTrue
e, da mesma forma,-
é novamente um número de byte ao subtrair o mesmo valor0
que será interpretado comofalse
portanto, podemos substituir
/
ou-
por qualquer caractere que desejarmos, por exemplo:Manterá o mesmo significado que a expressão original.
fonte
Vamos começar com true. Você pode lê-lo como
'/' / '/'
, o que significa "caractere '/' dividido pelo caractere '/'". Como cada caractere, em C, é um valor numérico (em um byte), ele pode ser lido como "o valor ASCII do caractere '/' dividido pelo valor ASCII desse mesmo caractere", o que significa 1 (porque, obviamente, x / x é 1). Conseqüentemente,TRUE
é 1.Pois
FALSE
, é o mesmo raciocínio:'-'-'-'
lê'-' - '-'
, ie "o valor ASCII de '-' menos o valor ASCII de '-'", que é 0. Portanto,FALSE
é 0.Esta é uma maneira desagradável de afirmar o óbvio.
fonte
'/'/'/'
é 1 para qualquer conjunto de caracteres válido, seja'/' == 47
(como em ASCII) ou'/' == 97
(como em EBCDIC) ou qualquer outro valor.'/'
a0
. Esse valor é reservado para o caractere nulo.