[C/C++] shift operator 사용 시 주의

2019. 7. 19. 03:00프로그래밍/C/C++

728x90
728x90

서론

  • 회사에서 pvs 정적분석 툴을 사용하는데 엔진 코드에 shift 연산자에 관한 검출 결과가 많았따.
  • https://www.viva64.com/en/w/v610/
  • 에러는 shift 연산자를 사용할 때 left, right 피연산자가 음수일 때, right 피연산자가 32를 넘어갈 때 등을 고려하고 있다.

예제

    const signed long long test[4] = {
        1024 << -1, (signed long long)1024 << -1,
        -1 << 32, (signed long long)(-1) << 32
    };
  • 나는 엔진코드를 잘 몰라서 이런 소스를 거의 본적이 없지만 -1을 << shift 연산자를 통해 -2^n을 표현할 수 있는 것 같다.
  • 이런 방식과 유사하게 여러 수식이나 계산을 하는 코드들이 pvs에 검출되었다.

right 피연산자가 -1인 경우

  • 우선 -1만큼 shift하는 것은 미정의 동작으로 VS2015 기준 C++ 컴파일러는 0을 리턴한다.
  • right 피연산자가 int num; 같이 선언되어 있다면 num이 음수가 될 가능성을 고려해야 한다.
        [0]    0    const __int64
        [1]    0    const __int64
  • 해결은 right 피연산자에 음수가 될 가능성을 배재하는 방식으로 코드를 짠다.

right 피연산자가 32보가 커질 수 있는 경우

  • "-1 << 32"에서 컴파일러가 -1을 어떤 타입으로 결정할지는 컴파일러마다 다르고 예상할 수 없다.
  • VS2015 기준 C++ 컴파일러는 해당 정수를 int 타입으로 취급하고 있으며 이는 32비트 표현 한계를 가진다.
  • right 피연산자가 32보다 큰 경우 shift 범위가 int 타입 표현 한계를 넘어버려 미정의 동작일 수 있다는 이야기.
        [2]    0    const __int64
        [3]    -4294967296    const __int64
  • 해결은 캐스팅을 통해 left 피연산자의 타입을 확실히 지정해준다.
  • 32 이상이 문제라고 나오고 있지만 사실상 컴퓨터가 표현할 수 있는 범위를 넘는 right 피연산자가 존재하면 안되는 것이라 생각한다.
  • 현재는 64비트가 제한 기준이지만 나중에 128, 256이 나오면? 그러므로 right 피연산자의 범위 체크 코드를 예쁘게 짜놔야 될 것이라 생각한다.
728x90
반응형

'프로그래밍 > C/C++' 카테고리의 다른 글

[C] 예전 스타일 함수 선언. K&R-Style Declarations  (1) 2019.07.23
[VS] tab, space 보기  (0) 2019.02.27
[Boost] 설치  (0) 2016.03.19
[C++] for each 써보기  (2) 2016.01.19
[C++, Json] jsoncpp 사용하기  (5) 2016.01.06
[C/C++] 삼항 연산자  (4) 2015.11.27
[C++11] 주요 기능들  (0) 2015.09.07