usual_arithmetic_conversions — 일반 산술 변환

usual_arithmetic_conversions — 일반 산술 변환 (Usual arithmetic conversions)

많은 이항 연산자가 산술(arithmetic) 또는 열거형(enumeration) 타입의 피연산자를 기대하는데, 이런 연산자들은 피연산자를 변환하고 비슷한 방식으로 결과 타입을 만들어내요. 그 목적은 **공통 타입(common type)**을 만들어내는 것이고, 그 타입이 결과 타입이 되기도 해요. 이 패턴을 **일반 산술 변환(usual arithmetic conversions)**이라고 불러요.

출처: cppreference

본문

정의 (Definition)

일반 산술 변환은 다음과 같이 정의돼요.

1단계

두 피연산자에 lvalue-to-rvalue 변환을 적용해요. 결과적인 prvalue들을 나머지 과정에서 원래 피연산자 대신 사용해요.

2단계

C++11부터, 만약 어느 한 피연산자가 어떤 타입이면 다음과 같이 처리해요.

// 두 피연산자를 공통 타입으로 승격
short a = 1, b = 2;
int c = a + b;        // short → int 승격 (정수 승격)

정수 승격(integral promotion): char, short, bool, enum 같은 작은 정수 타입이 int(또는 unsigned int)로 승격돼요.

// 부호 없는 타입과의 혼합
unsigned int u = 10;
int n = -5;
auto r = u + n;   // int → unsigned int로 변환 (공통 타입 = unsigned int)
                  // 결과는 큰 unsigned 값

부동 소수점 피연산자끼리는 작은 쪽이 큰 쪽으로 승격돼요.

float f = 1.0f;
double d = 2.0;
auto r = f + d;   // float → double, 결과 double

일반 산술 변환의 규칙 요약 (2단계 이후):

  1. 어느 한쪽이 long double이면 다른 쪽도 long double로 변환.
  2. 아니면 어느 한쪽이 double이면 다른 쪽도 double로.
  3. 아니면 어느 한쪽이 float이면 다른 쪽도 float로.
  4. 아니면 정수 승격을 적용한 뒤, 두 타입이 같아질 때까지 부호 있는/부호 없는 정수 규칙을 적용.
// 정수 규칙의 함정
int i = -1;
unsigned int u2 = 1;
std::cout << (i < u2);   // i가 unsigned로 변환되어 거대한 수 → false

일반 산술 변환을 이해하는 것은 특히 부호 있는/부호 없는 정수 혼합에서 예기치 않은 값을 방지하는 데 필수적이에요. 음수와 unsigned를 비교하거나 연산하면 놀라운 결과가 나올 수 있어요.

더 알아보기 (Learn more)

cppreference