조건문의 분기를 줄여보자!

int x에 대해

if(x < 0 || x > d) //라는 조건이 있으면
if((unsigned) x > d) //로 바꿔 연산을 간단하게 할 수 있습니다.

끄적거려봤어요…

3 Likes

실제로 a < x < b 에 대한 일부 컴파일러 최적화도 이렇게 되었던거같읍니다. :+1:

lb <= x && x < ub(unsigned)x - lb < ub - lb로…

참고로 최적화 전과 최적화 후 결과는 다음과 같습니다. (Clang 8.0/GCC 9.1, -O3)

Before

bool outOfRange(int num, int k) {
    return num < 0 || num > k;
}
outOfRange(int, int):                       # @outOfRange(int, int)
        test    edi, edi
        sets    cl
        cmp     edi, esi
        setg    al
        or      al, cl
        ret

After

bool outOfRange(int num, int k) {
    return (unsigned) num > k;
}
outOfRange(int, int):                       # @outOfRange(int, int)
        cmp     edi, esi
        seta    al
        ret
3 Likes

이거 코세님이 2년전인가 제 코드 고쳐주실때 팁주셨었는데 기억 새록새록

2 Likes

그거 저임미다ㅠㅠ

1 Like

제코드도 고쳐주셨음!

안녕하세요.

컴파일러가 최적화를 해준다면, 굳이 사람이 저런식으로 코드를 짤 필요는 없는거 아닐까요?

코드를 읽는 입장에서는 위에 코드가 훨씬 더 직관적일테니까요. ㅎㅎㅎ

1 Like

앗… ㅈㅅㅈㅅㅈㅅ

위에 얼음나무님이 올려주신것처럼, 최적화한 결과에서 인스트럭션이 줄어든다면 나름 기교를 발휘해보는것도 나쁘진 않다고 생각합니다.

사람 입장에서는 동일한 동작이지만 기계 입장에서는 다르니까요.

내친김에 이것도…(GCC 8.3, -O3)


auto boundary_check(int x, int lb, int ub)
{
      return lb <= x && x < ub;
}
boundary_check(int, int, int):
        cmp     esi, edi
        setle   al
        cmp     edi, edx
        setl    dl
        and     eax, edx
        ret

auto boundary_check(int x, int lb, int ub)
{
      return (unsigned)x - lb < ub - lb;
}
boundary_check(int, int, int):
        sub     edi, esi
        sub     edx, esi
        cmp     edi, edx
        setb    al
        ret

흥… 실망이 큽니다.

아냐 나도 지적해줬어.
다른 코드였을껄?

2 Likes

맞아여 처음 저거 봤을땐 충격이 어마어마해서 막 난리쳤던걸로 기억 ㅋㅋㅋ (근데 쫄보라 unsigned 안 쓰다가 까먹은…)

언사인드랑 인트 비교하다가는 큰일 날 수도 있음
저는 그냥 인트만 쓰는 걸로…

자-바 하십시오

죄송합니다…

앗 왜그런건가요 혹시 설명좀 부탁드려도 될까요?

안녕하세요.

C/C++에 있어서 unsigned 형은 조심해서 사용하셔야 합니다.
왜냐하면 연산에 있어 특별한 규칙이 적용되기 때문이죠.

정확히는 기억이 안나지만, 제가 알고있기로는,

  1. 수식에서 unsigned와 signed를 혼용하면 결과값의 타입은 unsigned다.(signed가 암시적 형변환이 일어납니다.)
  2. unsigned형이 음수가 되면 underflow가 일어난다.

위와 같은 위험성을 인지하지 못한채로 사용한다면 코드가 의도와는 다르게 작동할 수 있죠.
예를 들어 다음과 같은 코드가 있을 수도 있겠네요.

unsigned int i;
for ( i = 5; i >= 0; --i ) { //DO SOMETHING }

이런식으로 작성하게 된다면 문제가 발생하겠죠??

그리고

이분 말씀은 자바에는 unsigned형이 없다. 이런 말씀입니다.

자바에 unsigned가 없는 가장 주된 이유라고 생각합니다.

1 Like