2014-09-01 5 views
1

ANSI C의 상수 (리터럴)에 접미어 (후치)를 잊어 버리면 어떻게 될지 설명 할 수 있습니까? 그것은 32 비트 아키텍처에리터럴 접미사 U, UL 문제

#define AAR_INTENSET_NOTRESOLVED_Pos (2UL) /*!< Position of NOTRESOLVED field. */ 
#define AAR_INTENSET_NOTRESOLVED_Msk (0x1UL << AAR_INTENSET_NOTRESOLVED_Pos) /*!< Bit mask of NOTRESOLVED field. */ 
#define AAR_INTENSET_NOTRESOLVED_Disabled (0UL) /*!< Interrupt disabled. */ 
#define AAR_INTENSET_NOTRESOLVED_Enabled (1UL) /*!< Interrupt enabled. */ 
#define AAR_INTENSET_NOTRESOLVED_Set (1UL) /*!< Enable interrupt on write. */ 

을 사용되는 :

예를 들어 나는 비트 시프트 연산 등의 정의를 보았다. 그러나 16 비트 또는 8 비트로 이식 될 수 있습니다. postfix UL을 사용하지 않고 비트 시프트 작업에이 매크로를 사용한다면 어떻게됩니까?

8 비트 아키텍처에서 (1 < < 30) 오버 플로우가 발생할 수 있습니다.

편집 : 나는 좋은 링크를 발견 : http://dystopiancode.blogspot.cz/2012/08/constant-suffixes-and-prefixes-in-ansi-c.html

을하지만 코드가 다양한 아키텍처에 포팅 될 것으로 예상되는 경우 접미사를 사용하는 것이 안전합니다?

예를 들어 접미사 U가 unbitned int를 나타내는 경우 8 비트 아키텍처의 경우 보통 16 비트이지만 32 비트 변수는 32 비트이므로 0xFFFFAAAAU는 32 비트 컴파일러에서는 괜찮지만 8 비트 컴파일러에서는 그렇지 않습니다.

+2

"8 비트 아키텍처"는 "최대 255 개까지만 계산할 수 있습니다"와 같지 않습니다. 버스 길이보다 긴 모든 계산을 더 쉽게 소화 할 수있는 덩어리로 변환하는 것은 컴파일러의 몫입니다. – usr2564301

답변

5

접미사가없는 -1,1,2,12345678 등과 같은 십진수는 int, long, long long으로 시작하는 가장 작은 유형이됩니다.

같은 8 진수 또는 16 진수 숫자 0, 0123, int, unsigned, long, unsigned long, long long, unsigned long long로 시작하는이 맞는 작은 유형을 얻을 것이다 접미사없이 0x123, 0X123.


다음 잠재적 문제 AAR_INTENSET_NOTRESOLVED_Pos이 31 주 이상이어야이다 unsigned long 적어도 32 비트이어야한다. unsigned long이 32 비트이면 0 **가되고 더 길면 0이됩니다.

(0x1UL << AAR_INTENSET_NOTRESOLVED_Pos) 

다음

유사한 잠재적 문제 AAR_INTENSET_NOTRESOLVED_Pos 15. 0x1 만 적어도 16 비트이어야합니다 unsigned이다 초과해야한다. 또한 unsigned/int이 16 비트 인 경우 최소 0x1int이됩니다. 그러므로 U을 명시 적으로 사용하지 않고 AAR_INTENSET_NOTRESOLVED_Pos == 15 인 경우 0x1이 문제가 될 수 있습니다.[@ 매트 McNabb]

(0x1 << AAR_INTENSET_NOTRESOLVED_Pos) 

비트 시프트 연산자
"정수 프로모션 피연산자들 각각에 대해 수행되는이. 결과의 유형 촉진 왼쪽 피연산자이다. 값이면 오른쪽 피연산자의 너비가 음수이거나 승격 된 왼쪽 피연산자의 너비보다 크거나 같으면 동작이 정의되지 않습니다. " C11dr §6.5.7 3


기계 너비는 주요 문제가 아닙니다. 8 비트 또는 16 비트 머신은 16, 32 등을 사용할 수 있습니다. 비트 크기는 int입니다. 다시 말하지만, 16 비트는 호환되는 C 컴파일러의 최소 크기입니다.


[편집] ** I 상기해야 "이 정의되지 않은 동작이 발생할 것이다 (이상 31 비트 시프트) UBunsigned long 경우 32 비트이다."

+0

OK ...'0x1 "15"는 int가 16 비트이기 때문에 UB (부호있는 정수 오버플로)를 발생 시키므로 "초과 15"는 "같거나 15를 초과해야합니다"또는 유사한 것 –

+0

@Matt McNabb 가리키는 것에 감사드립니다 그 오류도 해결되었습니다. – chux

0

깨질 수 있습니다.

코드 자체의 캐스트를 포함하는 더 좋을 수도, 즉

uint32_t something = (uint32_t) AAR_INTENSET_NOTRESOLVED_Set << 30; 

이는 상수에 대한 #define 단순히 정수 경우에도 작동합니다.