2014-06-23 2 views
1

나는 다음과 같은 코드 조각이 :경고 : 기본적으로 사용] 유형의> = 폭 왼쪽 시프트 수

long int compute_data_length(unsigned char* buf, int data_offset) { 

long int len; 

if(!buf) 
    return -1; 

switch(data_offset) { 
    case 2: { 
       len = (buf[2] << 8) | buf[3]; 
      } 
      break; 
    case 8: { 
       len = (buf[2] << 56) | 
         (buf[3] << 48) | 
         (buf[4] << 40) | 
         (buf[5] << 32) | 
         (buf[6] << 24) | 
         (buf[7] << 16) | 
         (buf[8] << 8) | 
         (buf[9]  ); 
      } 
      break; 
    default: len = -1; break; 
} 
return len; 
} 

내가 컴파일 할 때, 나는 다음과 같은 경고 얻을 :

math_fun을 .c : 240 : 21 : 경고 : 왼쪽 시프트 수> = 유형의 너비 [기본적으로 사용 가능] len = (buf [2] < < 56) | ^ math_fun.c : 241 : 27 : 경고 : 왼쪽 시프트 수> = 유형의 너비 [기본적으로 사용 가능] (buf [3] < < 48) | ^ math_fun.c : 242 : 27 : 경고 : 왼쪽 시프트 수> = 유형의 너비 [기본적으로 사용 가능] (buf [4] < < 40) | ^ math_fun.c : 243 : 27 : 경고 : 왼쪽 시프트 수> = 유형의 너비 [기본적으로 사용 가능] (buf [5] < < 32) |

경고를 어떻게 수정합니까?

+2

'long int'의 크기는 얼마나됩니까? 이동을하기 전에 올바른 유형으로 캐스트하십시오. – Deduplicator

+0

-bash-4.1 $ ./a.out long int 8 long long의 크기 8 unsigned long 8 –

+0

[부호없는 정수 필드 시프트는 부호있는 정수를 산출합니다] (http://stackoverflow.com/questions/22152636/)와 밀접하게 관련됩니다. 부호가없는 정수 비트 필드 시프트 수율 부호있는 정수/22152886 # 22152886), 울타리인지 여부는 dup인지 여부를 결정합니다. –

답변

5

정수 승수는 (int)buf[2] << 56 [참고 1]로 바꾸지 만, int은 32 비트 만 가능하며 의미있는 시프트를 위해서는 부호없는 64 비트 유형이어야합니다.

unsigned long은 64 비트가 될 것으로 예상되지만 그렇지 않을 수도 있습니다. <stdint.h>을 포함하고 uint64_t을 사용하는 것이 좋습니다. 어떤 경우에, 당신은 명시 적으로 왼쪽 Shift 왼쪽 피연산자 캐스팅해야합니다

((uint64_t)buf[2] << 56) | ... 

[참고 1] : unsigned charint만큼 넓게하는 것이 이론적으로 가능하는 정수 경우 프로모션은 unsigned int입니다. 하지만 이는 특이한 아키텍처에서만 발생합니다.

+1

이 답변의 품질에 실제로 영향을 미치지 않는 사소한 세부 사항이지만'buf [2]'는 거의 항상'unsigned int'가 아닌'int'로 승격됩니다. –

+0

@MichaelBurr : 좋은 지적입니다. 편집 됨. – rici

+0

C99에서'unsigned char'가'int'만큼 넓지는 않을 것이라고 생각합니다. 'uint8_t '의 존재는'unsigned char'이 8 비트 폭이라는 ​​것을 의미하는 것 같지만'int'는 그 이상이어야합니다. –

0

경고 읽기 알아주세요

math_fun.c : 240 : 21 : 경고 : 기본적으로 사용] 유형> = 폭 좌측 시프트 수 렌 = (BUF [2] < < 56) | 당신이 오류를 이해할 필요가 있고 그것을 해결하는 방법에 대해 모든 정보를 제공합니다^

:

당신이 긴 미만 56 비트 이동 유형, 그래서 56 비트 이상의 이동은 정의되지 않은 동작입니다.
먼저 더 큰 유형으로 먼저 전송하십시오.

나중에이 결과를 할당 할 변수의 유형이기 때문에 플랫폼에 청구서를 넣기를 바랍니다. int64_t으로 제공 될 경우 충분히 커야합니다 ().

여기에 unsigned 유형 만 사용하는 것이 좋습니다. signed 유형의 오버플로는 정의되지 않습니다.