public long SomeMethod(int id)
{
long newId = id << 32 + id;
return newId;
}
위 식에서 id가 10000이라면 무슨 값이 나올까?
long newId = 10000 << 32 + 10000;
일테니, 10000을 왼쪽으로 32번 시프트하고, 10000을 더한 값이 들어갈 것이라고 생각할 수 있다.
하지만, 실제로는 비트 연산자의 우선 순위가 더하기 연산자보다 우선순위가 낮기 때문에
long newId = 10000 << (32 + 10000);
결과적으로는 위 식과 같은 식이며, 좌측으로 10032번 시프트를 한 결과가 나오게 된다.
이 녀석의 무서운 점은 에러 따위를 띄우지 않는다는 점이다. -_-;; 코드만 보고 id를 32비트만큼 왼쪽으로 옮긴 후 더해서 Unique한 새로운 id를 만드는 역할인가보다 라고 생각하면 큰코를 다칠 수가 있다.
비트 연산자를 총 비트의 수보다 더 많이 시프트하면 나오는 결과는 시스템마다 다를 수 있다고 한다.
유니티 에디터에서는 이렇게 많은 시프트 연산을 해도 문제가 발생하지 않았고, 아이폰에서도 문제없이 작동했던 것으로 봤다.
그런데 안드로이드에서는 간헐적으로 문제가 발생했다. 평소엔 잘 되다가 어떨 때는 문제가 발생하고, 껐다 켜면 괜찮아지기도 하고, 다시 껐다 켜면 이상해지기도 하고(...)
원인은 시프트 연산을 너무 많이 해서 비정상적인 값이 출력된 것으로 확인되었다. 디버그를 찍어보니 id가 다른데도 동일한 결과가 나오고 있던 것. (0이 나올 때도 있었고, 마이너스로 큰 값이 나올 때도 있었다.)
public long SomeMethod(int id)
{
long newId = (id << 32) + id;
return newId;
}
때문에 위 식으로 수정했고, 이후 정상적으로 동작하게 되었다.
비트 연산자와 다른 연산자를 같이 사용할 때는 우선순위에 주의하도록 하자.
'개발 > 공부' 카테고리의 다른 글
[C#] Nullable을 활용한 효율적이고 안전한 개발 (0) | 2024.08.25 |
---|---|
메모리 관리에 대한 탐구 (10) - Unity에서 Font 관련 용량 줄이기 (2) | 2024.05.12 |
[Unity] Time.realtimeSinceStartup 은 정확도가 떨어진다. (1) | 2024.05.09 |
JetBrains Rider의 장점을 활용해서 효율적인 개발하기 (0) | 2023.09.16 |
메모리 관리에 대한 탐구 (9) - Addressables와 메모리 관리 (0) | 2023.08.20 |