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단계 이후):
- 어느 한쪽이
long double이면 다른 쪽도long double로 변환. - 아니면 어느 한쪽이
double이면 다른 쪽도double로. - 아니면 어느 한쪽이
float이면 다른 쪽도float로. - 아니면 정수 승격을 적용한 뒤, 두 타입이 같아질 때까지 부호 있는/부호 없는 정수 규칙을 적용.
// 정수 규칙의 함정
int i = -1;
unsigned int u2 = 1;
std::cout << (i < u2); // i가 unsigned로 변환되어 거대한 수 → false
일반 산술 변환을 이해하는 것은 특히 부호 있는/부호 없는 정수 혼합에서 예기치 않은 값을 방지하는 데 필수적이에요. 음수와 unsigned를 비교하거나 연산하면 놀라운 결과가 나올 수 있어요.