TRUE 및 FALSE 매크로의 이상한 정의


300

코딩 북에서 다음과 같은 매크로 정의를 보았습니다.

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

거기에 대한 설명이 없었습니다.

다음과 같이 작동하는 방법을 나에게 설명해주십시오 TRUEFALSE.


63
TRUE를 1로, FALSE를 0으로 정의하는 것이 재미있는 방법이라고 생각합니다.
BlackDwarf

160
이것은 표현식 주위에 괄호가없는 끔찍한 아이디어입니다. 나는 그것이 끔찍한 생각 의미 그들,하지만 당신은 단지 디버깅의 긴 밤을 요청하고 않고.
TartanLlama

70
참조하는 코딩 북을 알고 있습니까?
artm December

47
이 책에 잘못되었거나 의도적으로 모호한 코드의 예가 포함되어 있기를 바랍니다.
Jon Hanna

31
@Daniel : 또 다른 아이디어는 rand () % 2가 MAYBE를 rand () % 2로 정의하는 것이므로 가끔 == TRUE이고 때로는 == FALSE입니다.
Kaiserludi

답변:


380

보자 : '/' / '/'수단 char문자 /에 의해 구분, char문자 그대로의 '/'자신을. 그 결과는 합리적으로 들리는 것입니다 TRUE.

그리고 문자 자체를 빼는 '-' - '-'것을 의미합니다 . 이것은 0 입니다.char'-'FALSE

이것에는 두 가지 문제가 있습니다 : 첫째, 읽을 수 없습니다. 사용 1하고 0절대적으로 좋습니다. 또한 TartanLlama와 KerrekSB가 지적했듯이 그 정의를 사용하려는 경우 괄호를 추가하여 놀라지 않도록하십시오.

#include <stdio.h>

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

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

이것은 char리터럴 의 값을 인쇄합니다 '-'(시스템의 45).

괄호로 :

#define TRUE  ('/'/'/')
#define FALSE ('-'-'-')

진리 값에 정수를 곱하는 것이별로 의미가 없지만 프로그램은 0을 올바르게 인쇄하지만 매크로를 괄호로 묶지 않으면 예상치 못한 버그의 예일뿐입니다.


6
젠장, 나는 그것을 이해하기 위해 많은 걸렸다 : 심지어 글리프처럼 이상한 일이라고 생각 ... xD를 몰라
루이스 Masuelli

8
실제로 진실 가치를 곱하는 것이 합리적입니다. 예를 들어 들여 쓰기 * should_indent는 분기없이 should_indent인지에 따라 0 또는 들여 쓰기가됩니다. (텍스트 단일 분기 작업을 할 때 이것이 나쁜 예라고 생각합니다. (이 기법을 셰이더와 XPATH에서 보았습니다 (너무 다르고 정확한 형식을 기억하지 못합니다))
Alpedar

2
Alpedar는 -하지만하지 않는 개념 및 matehmatically 그렇게 열차 만들기 -이 경우는 명확하게 (그리고 개념적으로 이해)을 사용하는 것 if대신 곱의 TRUE정수로.
Jay

4
좋은 설명입니다. 금 배지를 받으십시오!
Michael Hampton

2
논리적 부정은 그대로 구현되어 notx = TRUE- x;작동 할 수 있습니다 . 이 제외 TRUE-FALSE-44이다 (가정 ASCII)
하겐 폰 Eitzen

89

그것은 또 다른 쓰기 방법입니다

#define TRUE 1
#define FALSE 0

이 표현식 '/'/'/'은 char 값을 '/'자체적으로 나누므로 결과적으로 1이됩니다.

이 표현식 '-'-'-'은의 char 값을 뺍니다.'-' 자체에서 결과적으로 0을 제공합니다.

define그러나 전체 표현식 주위에 대괄호 가 누락되어 이러한 매크로를 사용하는 코드에서 오류가 발생할 수 있습니다. 제이의 대답 그 점을 잘 보여줍니다.

대괄호를 잊어 버릴 수있는 "실제"시나리오의 예는 이러한 매크로를 C 스타일 캐스트 연산자와 함께 사용하는 것입니다. 예를 들어 누군가가 boolC ++에서 이러한 표현식을 캐스트하기로 결정한 경우 :

#include <iostream>

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

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

우리가 얻는 것은 다음과 같습니다.

True: 0
False: -44

그래서 (bool) TRUE사실에 평가하는 것 false, 그리고 (bool) FALSE로 평가 것입니다 true.


4
좋은 예입니다 :)
Kit Fisto

44

쓰기에 해당합니다

#define TRUE 1
#define FALSE 0

표현식이 '/'/'/'실제로하는 일은 문자 /(숫자 값이 무엇이든)를 자체적으로 나누는 것 1입니다.

마찬가지로 표현식 '-'-'-'은 문자 -자체를 빼고로 평가합니다 0.

쓰는 것이 좋습니다

#define TRUE ('/'/'/')
#define FALSE ('-'-'-')

우선 순위가 높은 다른 연산자와 함께 사용할 때 실수로 값이 변경되는 것을 방지합니다.


5
롤! 그렇기 때문에 매크로를 괄호로 묶어야합니다.
0605002

구에 대한 3 권의 권리와 같은 장소에있게됩니다
Derek 朕 會 功夫

@KerrekSB 아니오, 그러나 3 개의 왼쪽은 :)
Tim Long

33

제이는 이미 이러한 식의 값이 왜 대답 0하고 1.

역사를 위해,이 표현 '/'/'/''-'-'-'의 항목 중 하나에서 오는 1984 년 제 1 회 국제 난독 C 코드 대회 :

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);}

( 여기 의 프로그램 링크 는 위의 IOCCC 페이지에이 프로그램의 기능에 대한 힌트가 있습니다.)

나는에 대한 난독 매크로로 제대로 이러한 식을 기억 또한 경우 TRUEFALSE도 덮여 있었다 "난독 C 및 다른 신비" 돈 리브 (Don Libe) (1993)에 의해 책.


7

에 대한 매크로를 작성하기위한이 재미 방법 TrueFalse.

많은 설명이 제공되었으므로 /1 바이트 숫자 (ASCII 당)는 자체로 나눌 때 1처리 할 것과 같은 값을 빼면 바이트 번호 True와 같이 처리 됩니다.-0false

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

따라서 다음 과 같이 원하는 문자로 바꾸 /거나 바꿀 수 있습니다 -.

#define TRUE  '!'/'!'
#define FALSE 'o'-'o'

원래 표현과 같은 의미를 유지합니다.


6

true로 시작합시다. 로 읽을 수 있습니다. '/' / '/'"문자 '/'를 문자 '/'로 나눈"을 의미합니다. C의 각 문자는 1 바이트 단위의 숫자 값이므로 "문자 '/'의 ASCII 값을 동일한 문자의 ASCII 값으로 나눈 ASCII 값"으로 읽을 수 있습니다. 이는 1을 의미합니다. x / x는 1)입니다. 따라서 TRUE1입니다.

에 대한 FALSE동일한 추론 : '-'-'-'reads '-' - '-', 즉 " '-'의 ASCII 값에서 '-'의 ASCII 값을 뺀 값 FALSE-0 "-따라서 0입니다.

이것은 명백한 것을 언급하는 불쾌한 방법입니다.


7
이것은 ASCII와 관련이 없습니다.
Kerrek SB

6
@Fabien : ASCII에 의존 하지 않습니다 . '/'/'/'1 인 모든 유효 자 세트의 여부 '/' == 47(이는 ASCII에서와 같이), 또는 '/' == 97(이 EBCDIC에서와 같이), 또는 임의의 다른 값.
Keith Thompson

4
@Pawel : 적합하는 C 구현은 매핑 할 수 없습니다 '/'0. 이 값은 널 문자 용으로 예약되어 있습니다.
Keith Thompson

2
당신은 pedantic되고 있습니다.
Matheus208

3
@ Matheus208 만약 Pawel이 현혹 적이라면, 그의 주장은 언급되지 않은 상태에 근거한 것이기 때문에 ( '-'-'-')입니다. Pedantic이라고 Keith의 발언을 설명하는 것이 더 많을 수도 있지만 ( '/'/ '/') 나는 그것들을 "명확하게"라고 부를 것입니다. 함께 찍은 의견을 pedantic이라고 부를 수는 있지만 ( '-'/ '-') 1)이 분야에서는 다소 의무적이지 않습니까? 2) 그들은 나를 생각하게했다; 그리고 3) 나는 나보다 어떤 것들에 대해 조금 더 명확하다. 그리고 네, 제가 스스로 미친 듯이 생각하고 있습니다! (그러나 나는 "
보행자
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.