문제

운동으로 정수 변수가 서명되었는지 알려주는 매크로를 작성하고 싶습니다. 이것이 지금까지 가지고있는 것이며 GCC -fsigned -char 또는 -funsigned -char와 함께 Char 변수에서 이것을 시도하면 기대할 것으로 예상됩니다.

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

이것은 휴대용입니까? 변수의 값을 파괴하지 않고이 작업을 수행하는 방법이 있습니까?

도움이 되었습니까?

해결책

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

V의 값을 변경하지 않습니다. 세 번째 테스트는 V == 0 인 경우를 처리합니다.

내 컴파일러 (gcc/cygwin)에서 이것은 int 그리고 long 그러나 그렇지 않습니다 char 또는 short.

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

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

다른 팁

GCC를 사용하는 경우 사용할 수 있습니다 typeof 값을 덮어 쓰지 않는 키워드 :

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

이것은 임시 변수를 만듭니다. _V, 그것은 같은 유형을 가지고 있습니다 V.

휴대성에 관해서는 모르겠습니다. 그것은 둘의 칭찬 머신 (즉, 코드가 모든 확률로 실행될 모든 것)에서 작동하며, 칭찬과 사인 및 제작 기계에도 작동 할 것이라고 생각합니다. 참고로 사용하는 경우 typeof, 당신은 캐스팅하고 싶을 수도 있습니다 -1 에게 typeof (V) 더 안전하게 만들기 위해 (즉, 경고를 유발할 가능성이 적음).

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

변수의 값을 파괴하지 않고. 그러나 0 값은 작동하지 않습니다.

는 어때:

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

모든 "부정적인"대답에 대한 다른 접근법 :

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

이렇게하면 v v ∈ ℤ, v^v = 0이므로 V의 다른 값에 대해 특별한 경우가 필요하지 않습니다.

이 간단한 솔루션은 V를 한 번만 언급하는 이점 (매크로에서 중요 함)을 포함하여 부작용이 없습니다. GCC 확장자 "Typeof"를 사용하여 V 유형을 얻은 다음이 유형으로 -1을 캐스팅합니다.

#define IS_SIGNED_TYPE(v)   ((typeof(v))-1 <= 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;
}

모든 기본 적분 유형에 대한 상자 밖으로 작동합니다. 포인터의 컴파일 타임에서도 실패 할 것입니다. 포인터는 뺄셈과 비교 만 사용하는 버전은 아마 그렇지 않을 것입니다.

편집하다: 죄송합니다. 질문에는 C가 필요합니다. 여전히 템플릿은 좋은 방법입니다.

서명/부호없는 수학의 구별되는 특성은 서명 된 번호를 오른쪽으로 바꾸면 가장 중요한 비트가 복사된다는 것입니다. 서명되지 않은 숫자를 바꾸면 새 비트는 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의 보완 산술을 가정하지만 일반적으로 안전한 가정입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top