내 모듈에 코드 조각이 있고 ICC 컴파일러로 컴파일합니다.
/**
* Static (compile-time) assertion.
* Basically, use COND to dimension an array. If COND is false/zero the
* array size will be -1 and we'll get a compilation error.
*/
#define STATIC_ASSERT(COND) \
do { \
(void) sizeof(char [1 - 2*!(COND)]); \
} while (0)
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + \
(((off_t) 1 << 31) << 31))
STATIC_ASSERT(LARGE_OFF_T % 2147483629 == 721 &&
LARGE_OFF_T % 2147483647 == 1);
위의 주장이 실패하고 배열 크기는 0보다 커야합니다.
누구든지이 주장이 언제 실패하고 어떻게 고칠 수 있는지 이해하도록 도울 수 있습니까? _DFILE_OFFSET_BITS = 64로 컴파일을 시도했지만 헛된 것입니다.
코드 off_t
는 부호 비트를 포함하여 폭이 64 비트 이상 인지 확인하려고 시도합니다 .
이어 STATIC_ASSERT
,이 경우 COND
, 참 1 - 2*!(COND)
으로서 평가하여 1-2*!1
= 1-2*0
= 1
, 상기 배열 크기가 미세하다 1이다. 경우 COND
거짓, 그것으로 평가 1-2*!0
= 1-2*1
= -1
진단을 발행 할 수있는 컴파일러가한다. 따라서 거짓 STATIC_ASSERT
이면 컴파일러 메시지를 생성하는 역할을 COND
합니다.
LARGE_OFF_T
off_t
유형 에서 일부 산술을 수행하려고합니다 . off_t
너비가 64 비트 이상 이면 (off_t) 1 << 31) << 31
2 62로 평가됩니다 . 그런 다음 전체 표현식은 2 62 − 1 + 2 62 = 2 63 −1로 평가됩니다. 이 숫자는 나머지 721 모듈로 2147483629 및 1 모듈로 2147483647이므로 테스트를 통과하고 컴파일러에서 진단을 실행하지 않습니다.
경우 off_t
이고, 32 비트 폭과 부호, 말 (off_t) 1 << 31) << 31
(1) + 0 = 2 - 평가하여 0, 전체 표현식 평가하여 0 내지 32 -1 (부호 산술 랩 사람)와, 나머지 모듈 (37)의 2,147,483,629을 갖고, 실패 있도록 테스트 및 컴파일러가 진단을 생성합니다.
off_t
서명 된 경우 테스트를 신뢰할 수 없습니다 . 만약 off_t
서명 된 32 비트 폭의 동작은 (off_t) 1 << 31
C 표준에 의해 정의되지 않는다. 부호가 있고 너비가 63 비트 미만이면의 동작 ((off_t) 1 << 31) << 31
이 정의되지 않고 부호가 있고 너비가 64 비트 미만이면 최종 추가가 정의되지 않습니다.
테스트가 실패하면 off_t
최소 64 비트 너비의 정수 유형이 되도록 빌드 조건을 조정하여 수정해야합니다 . 이 작업을 수행하는 방법을 말하는 질문에 정보가 충분하지 않습니다.
코드 off_t
에 서명 된 유형이 될 것으로 예상 되는 표시가 있습니다. 서명되지 않은 것으로 알려진 경우 간단히 테스트하여 64 비트 이상인지 확인할 수 있습니다 18446744073709551615u <= (off_t) -1
. 그리고 코드가 생성하려고 시도하는 값인 2 63-1 은 부호없는 정수가 아닌 64 비트 부호있는 정수의 최대 값입니다. 위와 같이 off_t
부호가 있고 너비가 64 비트 미만인 경우 작업에 정의되지 않은 동작 이 있기 때문에 이는 불행한 일 입니다. 9223372036854775807 == (off_t) 9223372036854775807
서명 된 정수 유형으로 변환하는 동안 오버플로가 C 표준에 의해 정의되지 않는 것이 아니라 적어도 구현에 의해 정의되기 때문에 더 나은 접근 방식은 test 입니다. 하나는 또한 64 <= sizeof(off_t) * CHAR_BIT
. ( CHAR_BIT
에 정의되어 <limits.h>
있습니다.)
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다