2009-09-11 7 views
7

연습으로 정수 변수에 서명했는지 알려주는 매크로를 작성하고 싶습니다. 이것은 내가 지금까지 가지고있는 것이며 gcc -fsigned-char 또는 -funsigned-char를 사용하여 char 변수에서이 방법을 사용하면 예상되는 결과를 얻을 수 있습니다.C 정수 변수가 서명되었는지 어떻게 알 수 있습니까?

#define ISVARSIGNED(V) (V = -1, (V < 0) ? 1 : 0) 

이 휴대용 컴퓨터입니까? 변수의 값을 파괴하지 않고이를 수행 할 수있는 방법이 있습니까?

+0

이것은 호기심을 유발하는 문제이지만,이 정보에 대한 의도 된 용도에 더욱 더 흥미를 느끼고 있습니다. 입니다. 공유 할 기회가 있습니까? –

+0

이것이 C++에 RTTI가있는 이유입니다. :) –

+2

@jeffamaphone : 사실, 이것은 C++에서 템플릿이 빛나는 곳입니다. – sbi

답변

4
#define ISVARSIGNED(V) ((V)<0 || (-V)<0 || (V-1)<0) 

세 번째 테스트 케이스를 처리 V.의 값을 변경하지 않는 경우 제 컴파일러 (GCC/시그윈)이 char위한 intlong 아니라 작동에서 V의 == 0

또는 short.

#define ISVARSIGNED(V) ((V)-1<0 || -(V)-1<0) 

도 두 가지 테스트에서 작업을 수행합니다.

+0

Best 나는 아직 보지 못했습니다. 내가 볼 수있는 한 휴대용 표준 준수. –

+1

signed/unsigned short와 char을 구분하지 않습니다. 이러한 유형은 < == > 표현식을 평가할 때 int로 승격됩니다. – mob

+0

'short'와'char'에 대해 작동하게하려면, 변수를 사용하기 전에 변수를'char'에 캐스트 할 수 있습니다. 대부분의 오버 플로우 문제를 처리해야합니다. 내 생각 엔 ... –

5
#define ISVARSIGNED(V) ((-(V) < 0) != ((V) < 0)) 

변수 값을 손상시키지 않습니다. 그러나 0 값에는 작동하지 않습니다.

무엇에 대해 :

#define ISVARSIGNED(V) (((V)-(V)-1) < 0) 
+3

#define ISVARSIGNED (V) ((-V <0)! = (V <0)) – plinth

+0

예 C & Pd가 없어야합니다. 그 여분의 물건 ;-) – ypnos

+0

@ 플 린스, 당신은 "V"주위에 "여분의"뻔뻔한 매크로 확장에서 안전하게 만들었습니다 – rmeador

5

는 GCC를 사용하는 경우이 값을 덮어하지 않도록 typeof 키워드를 사용하여 다음을 가지고 그,이, _V를 임시 변수를 생성

#define ISVARSIGNED(V) ({ typeof (V) _V = -1; _V < 0 ? 1 : 0 }) 

V과 같은 유형입니다.

휴대성에 관해서는 잘 모르겠습니다. 2의 칭찬 시스템 (코드가 모든 확률로 실행될 수있는 모든 것)에서 작동하며,이 시스템이 칭찬 및 부호 및 크기 시스템에서도 작동 할 것이라고 믿습니다. 보조 메모로 typeof을 사용하는 경우 더 안전하게 (즉, 경고를 유발하지 않을 수 있도록) -1typeof (V) 번으로 캐스팅 할 수 있습니다.

+0

C++에서 정수 표현에 관계없이 Standard에서 작동하도록 보장됩니다 (n 비트의 경우 값은 2^n - 1 임). 나는 C 표준을 사용하기가 쉽지 않다. –

+0

나도 마찬가지지만 위키피디아 (모든 사실의 출처 : P)에서 C 표준이 나와있는 세 가지 표현을 허용한다는 것을 기억한다. 그 누구도 더 이상 그들을 사용하지 않습니다 ... –

-1

서명/서명되지 않은 수학의 특징은 서명 된 숫자를 오른쪽으로 이동할 때 가장 중요한 비트가 복사된다는 것입니다. 당신이 서명되지 않은 번호를 이동하면 새 비트는 0

#define HIGH_BIT(n) ((n) & (1 << sizeof(n) * CHAR_BITS - 1)) 
#define IS_SIGNED(n) (HIGH_BIT(n) ? HIGH_BIT(n >> 1) != 0 : HIGH_BIT(~n >> 1) != 0 

그래서 기본적으로,이 매크로는 숫자의 높은 비트가 설정되어 있는지 여부를 결정하는 조건식을 사용합니다. 그렇지 않은 경우 매크로는 비트를 비트 부정으로 설정합니다. 산술 부정은 -0 == 0이기 때문에 우리는 할 수 없습니다. 우리는 오른쪽으로 1 비트 이동하고 부호 확장이 발생했는지 테스트합니다.

이것은 2의 보수를 가정하지만 일반적으로 안전한 가정입니다.

+0

비트 시프트의 동작에 대한 이러한 가정에 대한 출처가 있습니까? –

+0

C99 표준 (6.5.7 절)은 부호가있는 음수 값의 오른쪽 시프트가 구현 정의임을 나타냅니다. 나의 해석은 2의 보완 기계에 부호 확장이있을 것이라는 점이다. C는 2의 보수 구조에만 국한된 것이 아니기 때문에 나오지 않을 것입니다. –

+0

마술'8' 대신에'CHAR_BITS'를 사용하면 더 많은 PC가 될 것입니다. (예, 알고 있습니다. 바이트 수가 8 비트 인 시스템에서는 작동하지 않습니다.) – sbi

1

이 간단한 솔루션에는 v를 한 번만 참조하면 (매크로에서 중요 함) 이점을 포함하여 부작용이 없습니다. 우리는 V의 유형을 얻기 위해 GCC 확장 "대해서 typeof"를 사용하고 주조 -1 유형 :

#define IS_SIGNED_TYPE(v) ((typeof(v))-1 <= 0) 

그것은 < = (활성화 된 경우) 단지 < 어떤 경우에 대한 컴파일러 경고를 방지하기보다는이다.

0

매크로가 필요한 이유는 무엇입니까?템플릿이 위해 중대하다 :

template <typename T> 
bool is_signed(T) { 
    static_assert(std::numeric_limits<T>::is_specialized, "Specialize std::numeric_limits<T>"); 
    return std::numeric_limits<T>::is_signed; 
} 

어느 모든 기본적인 통합 유형에 대한 아웃 - 오브 - 박스 작동합니다. 또한 포인터에 대한 컴파일시에는 빼기와 비교 만 사용하는 버전에서는 그렇지 않습니다.

편집는 : P

0

모든 "그것을 만들 부정적"답변에 대한 다른 접근 방식 :

#define ISVARSIGNED(V) (~(V^V)<0) 

그 방법 아차, 문제는 C. 스틸, 템플릿 좋은 방법 필요 012 V의 V 값을 가진 특별한 경우를 가질 필요는 없습니다.

관련 문제