2011-10-04 3 views
19

내 코드를 참조하십시오이 신비한 매크로 더하기 기호 stdint.h 무엇입니까?

#define INT8_C(val) ((int8_t) + (val)) 

이 더하기 기호의 의미 나 중요성은 무엇인가 :

#include <stdint.h> 

int main(int argc, char *argv[]) 
{ 
unsigned char s = 0xffU; 
char ch = 0xff; 
int val = 78; 
((int8_t) + (78)); /*what does this mean*/ 

INT8_C(val); /*equivalent to above*/ 

signed char + 78; /*not allowed*/ 

return 0; 
} 

을 내가 <stdint.h>의 매크로 정의입니다 찾기?

+1

'INT8_C'의 정의가 잘못 되었음 : 7.18.4 단락 3 : "이 매크로 중 하나의 호출 (참고 : 'INTN_C'참조)은 정수형 상수 표현으로 확장되어야하며,'# if' 전처리 지시어에 사용하기에 적합합니다. **"그 캐스트는 작동하지 않습니다 사전 처리 지시어에서는 전처리 중에 유형 (따라서 캐스트)이 존재하지 않기 때문에. 어떤 컴파일러/플랫폼을 사용하고 있습니까? 이에 대한 버그 리포트를 제출하는 것을 고려해야합니다. –

+4

@ChrisLutz : C99에서 유효했습니다. N1256에 통합 된 Technical Corrigendum 1에서는 무효가되었습니다. 이것은 [DR # 209] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_209.htm)에 대한 응답이었습니다. –

+0

@KeithThompson - 아. 나는 TC2 사본을 갖고 있으며, 꽤 최근까지는 기술 고문단을 실제로 알지 못했습니다. –

답변

27

코드 조각 :

((int8_t) + (78)); 

이는 표현은, 다음, 값 78 소요 단항 +을 적용 하나는 int8_t 유형, 전에 멀리 던지는 것을 던진다. 그것은 법적 표현에 진짜 차이가 없습니다 :

도 (컴파일러가 부작용이 없음을 알 수있는 경우 이러한 가능성이 존재에서 최적화 할 것이지만) 그 결과를 멀리 던져 식을 평가
42; 
a + 1; 

.

이러한 "누드"식은 C에서 완전히 유효하며 i++ 같이 i을 계산하여 부작용이있을 때만 유용하며 값을 증가시키는 부작용으로 버립니다.

당신이 이 매크로를 사용해야하는 방법이의 라인을 따라 더 :

int8_t varname = INT8_C (somevalue); 

겉으로는 중복 단항 + 연산자에 대한 이유는 표준에서 찾을 수 있습니다. 인용 부호있는 C99 6.5.3.3 Unary arithmetic operators /1 :

단항 + 또는 - 연산자의 피연산자는 산술 형식이어야합니다.

그리고, 6.2.5 Types, /18에 :

정수 및 부동 유형의 집합 연산 유형이라고합니다.

즉, 단항 +은 포인터, 복소수 또는 구조와 같은 매크로의 다른 모든 데이터 형식을 사용할 수 없도록합니다.

는 그리고 마지막으로, 이유 당신 :이 같은 일이 아니기 때문에

signed char + 78; 

조각이 작동하지 않습니다이다. 이 변수는 signed char 유형의 변수를 선언하기 시작하지만 유효한 변수 이름이 아니기 때문에 +에 도달하면 질식합니다. 당신의 작업 조각에이 상당하려면 다음을 사용 : signed char를 입력 할 수있는 값 +78의 캐스팅이다

(signed char) + 78; 

합니다.

그리고, C99 7.8.14 Macros for integer constants /2에 따라, 당신은 또한 그 매크로에 비 상수를 사용하여 조심해야한다는, 그들은 작동하지 않을 수있어 :

이 매크로의 인스턴스의 인수가이어야한다 해당 형식에 대한 제한을 초과하지 않는 값을 갖는 접미사가없는 정수 상수 (6.4.4.1에서 정의 된 )

6.4.4.1 단순히 다양한 접미사 (U, UL, ULL, L, LL와 소문자 당량 유형에 따라)을 가진 다양한 정수 포맷 (십진수/진수/헥스)를 지정한다. 결론은 변수가 아닌 상수이어야한다는 것입니다.

예를 들어, glibc이있다 : 수

# define INT8_C(c)  c 
# define INT16_C(c)  c 
# define INT32_C(c)  c 
# if __WORDSIZE == 64 
# define INT64_C(c) C## L 
# else 
# define INT64_C(c) C## LL 
# endif 

당신의 INT8_C 잘하지만 일할 매크로 텍스트 INT64_C(val) 당신이 원하는 것, 어느 것도 valL 또는 valLL, 하나에 사전 처리 될 것입니다.

+0

사실, OP가'INT8_C'에 대해주는 정의는 저의 독서로써 표준에 위배됩니다. 7.18.4 단락 3 : "이 매크로들 중 하나의 호출은 정수형 상수 표현 **으로 확장되어야합니다. **'# if' 전처리 지시어에 사용하기에 적합합니다. **" "INT8_C"의 원래 정의는 '# if' 지시자가 잘못되어있다. –

+3

@Chris : +는 전처리 지시어에서 +를 유효하게 만듭니다. 'int8_t'는 0으로 확장되고'(0) + (val)'은 단순히'val'입니다. –

+0

'int8_t'가 어떻게 0으로 확장됩니까? typedef라고 생각 했나요? o_O –

10

이것은 단 하나의 + 연산자입니다. 피연산자의 값을 산출하지만 산술 유형에만 적용 할 수 있습니다. 여기서 목적은 포인터 유형의 표현식에 INT8_C을 사용하지 못하도록하는 것입니다.

하지만 당신의 문장 표현

INT8_C(val); 

정의되지 않은 동작을 일으 킵니다. INT8_C()에 대한 인수는 "상응하는 유형에 대한 한계를 초과하지 않는 값을 가진 불완전 정수 상수"(N1256 7.18.4)가되어야합니다. 이 매크로의 목적은 INT64_C(42)과 같은 것을 작성하고 int64_tlong 일 경우 42L으로 확장하거나 int64_t이 길면 등 42LL으로 확장하도록하는 것입니다.

하지만 작성 중 하나를 자신의 코드에

((int8_t) + (78)); 

또는

((int8_t) + (val)); 

은 완벽하게 합법적이다.

EDIT :

질문에 INT8_C() 대한 정의 :

#define INT8_C(val) ((int8_t) + (val)) 

는 C99에서 유효하지만 비 순응 변화의 결과로서 나중에 N1256 초안에 따른 기술 고문 중 하나에

원래의 C99 표준 섹션 7.18.4.1p2는 말한다 :

매크로 INT *** N * _C ** () N을 규정 된 값을 부호있는 정수 상수로 확장 *** int_least을 입력해야 * _티**.

N1256은 (제 3 항)이 변화 :

이러한 매크로 중 하나를 호출 할 때마다 의 #if 전처리 지시문에 사용하기에 적합한 정수 상수 표현으로 확장한다. 표현식의 유형은 정수 판촉에 따라 변환 된 해당 유형의 표현 과 동일한 유형이어야합니다. 표현식의 값은 인수의 값이어야합니다.

Defect Report #209에 대한 응답으로 변경되었습니다.

EDIT2 :하지만 R ..의 대답을 참조하십시오. N1256에서 실제로 유효합니다. 이유는 분명하지 않습니다.

+1

OP의 코드가 잘못되었을뿐만 아니라 op의 stdint.h 복사본이 잘못되었습니다 (실제로는 INT8_C의 정의 인 경우). –

+0

@ChrisLutz : 뭐가 잘못 됐어? –

+0

그것은 7.18.4 문단 3을 위반합니다. 아래의 내 대답을 참조하십시오. –

0

그건 단항 플러스입니다.

일 수있는 것은 두 가지뿐입니다.

  1. 그것은 일반적인 산술 변환 피연산자에로 알고있는 것을 적용한다. 이 결과 실제 타입은입니다. 나는 결과가 특정 무언가에 던져 지려고하는 경우 이것을 강요 할 어떤 이유도 생각할 수 없다.

  2. 산술 연산자가 정의 된 유형으로 피연산자를 제한합니다. 이것은 더 많은 이유가있는 것처럼 보입니다.

18

모두가 #if 처리기 지시문에서 유효한 결과를 확인하는 것입니다 여기 단항 플러스 연산자의 요점을 놓친 것 같다. 을 감안할 때 :

#define INT8_C(val) ((int8_t) + (val)) 

지시어 :

#define FOO 1 
#if FOO == INT8_C(1) 

이 같은 확장 :

#if 1 == ((0) + (1)) 

예상대로 따라서 작동합니다. 이는 #if 지시어에있는 어떤 #define 심볼도 0으로 확장 되었기 때문입니다.

단항 더하기 (#if 지시어에서 이진수가됩니다)가 없으면 표현식이 #if 지시문에서 유효하지 않습니다.

+0

그건 정말 기괴하고 불행히도 작동합니다. 이 코드는 난독 화 된 C 코드로 간주됩니까? 하나의 상황에서는 단항 연산자이고 다른 것에서는 2 진수 연산자라고 생각하면, (int8_t)가 캐스트 또는 정의되지 않은 심볼로 해석되어서 난독 화를 경계하게됩니다 ... –

+0

만약 이것을 생각하면 tgmath.h를 읽지 마십시오 .... –

+1

동시에 아름답고 추악합니다. –

관련 문제