2014-12-21 2 views
28

난은 OpenSSL에서 사용되는 일부 처리기 매크로보고 있었다, 그리고 나는 crypto/stack/safestack.h에서 다음 건너 온 : 나는 그것은 컴파일러의 버그 (hasn 그 고대 아마 뭔가를 해결하기 위해 그런 식으로 작성 같은데요상수 (true) 값을 갖는 조건부 연산자?

#define CHECKED_STACK_OF(type, p) \ 
    ((_STACK*) (1 ? p : (STACK_OF(type)*)0)) 

#define CHECKED_SK_FREE_FUNC(type, p) \ 
    ((void (*)(void *)) ((1 ? p : (void (*)(type *))0))) 

#define CHECKED_SK_FREE_FUNC2(type, p) \ 
    ((void (*)(void *)) ((1 ? p : (void (*)(type))0))) 

공급 업체가 10 년 동안 지원해 왔음).

는 항상 true 이후 위의 1를 사용하는 목적은 무엇인가?

+3

조건부 연산자의 두 번째와 세 번째 피연산자가 같은 유형으로 변환 될 수있는 'p'유형을 확인해야합니다. –

답변

25

올바른 유형이 전달되는지 여부를 두 번 확인하는 코드입니다. 포인터 p는 전달되고 해당 포인터 유형을 따라 수동으로 매크로에 입력해야합니다.

삼항 표현은 항상 두 번째 피연산자를 반환하지만, 두 번째 및 세 번째 피연산자는 형식과 일치하는 경우 확인되며, 그렇지 않은 경우는 컴파일러 오류가 발생합니다.

간단한 예 :

int* p = NULL ; 

1 ? p : (float*)p ; //error 

1 ? p : (int*)p ;  //ok 
+0

고맙습니다. – jww

13

그것은 형식 안전 캐스트를 제공하는 주조하기 전에 기능 유형에 대한 정적 주장이다. C11에서

(n1570) 6.5.15 (제한 부)에서

조건 연산자

(3) 두 번째 및 세 번째 피연산자 보유한다 다음 중 하나 :

  • [생략 된 비 포인터 스터프]
  • 두 피연산자는 모두 정규화 또는 무 규정화 된 버전의 포인터입니다. 가용 유형;
  • 하나의 피연산자는 포인터이고 다른 하나는 널 포인터 상수입니다. 또는
  • 하나의 피연산자는 오브젝트 유형에 대한 포인터이고 다른 하나는 규정 된 또는 규정되지 않은 버전 void에 대한 포인터입니다. 하나 p가 널 포인터 상수 또는 void (*)(type)와 호환되는 형식의 경우에만

세 번째 피연산자는 함수 (그래서 마지막 총알이 적용되지 않음)에 대한 포인터입니다, 그래서 이것은 (경고없이) 컴파일 마지막 매크로 (함수 포인터로의 변환 후, p이 함수 지정자 인 경우).