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


300

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

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

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

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


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 페이지에이 프로그램의 기능에 대한 힌트가 있습니다.)

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


7

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

많은 설명이 제공되었으므로 /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.