Implicit conversions
표현식이 다른 타입의 값이 예상되는 맥락에서 사용될 때, 변환(conversion) 이 발생할 수 있습니다:
int n = 1L; // 표현식 1L은 long 타입을 가지며, int가 예상됨 n = 2.1; // 표현식 2.1은 double 타입을 가지며, int가 예상됨 char* p = malloc(10); // 표현식 malloc(10)은 void* 타입을 가지며, char*가 예상됨
변환은 다음과 같은 상황에서 발생합니다:
목차 |
할당에 의한 변환
- 대입 연산자에서 우변 피연산자의 값은 좌변 피연산자의 비한정 타입으로 변환됩니다.
- 스칼라 초기화 에서 초기화식의 값은 초기화되는 객체의 비한정 타입으로 변환됩니다.
- 프로토타입을 가진 함수에 대한 함수 호출 표현식 에서 각 인수 표현식의 값은 해당 매개변수의 비한정 선언 타입으로 변환됩니다.
- 반환문 에서 return 의 피연산자 값은 함수의 반환 타입을 가진 객체로 변환됩니다.
실제 대입은 변환 외에도 부동 소수점 타입에서 추가 범위와 정밀도를 제거하고 중첩을 금지한다는 점에 유의하십시오; 이러한 특성은 대입에 의한 변환처럼 적용되지 않습니다.
기본 인수 승격
함수 호출 표현식 에서 호출이 수행될 때
각 정수 타입 인수는 정수 승격 을 거치며, float 타입의 각 인수는 암시적으로 double 타입으로 변환됩니다.
int add_nums(int count, ...); int sum = add_nums(2, 'c', true); // add_nums가 세 개의 int로 호출됨: (2, 99, 1)
|
이 문맥에서 float complex 와 float imaginary 은 double complex 와 double imaginary 으로 승격되지 않습니다. |
(C99부터) |
일반 산술 변환
다음 산술 연산자의 인수들은 계산이 수행되는 타입인 공통 실수 타입 을 얻기 위해 암시적 변환을 거칩니다:
- 이항 산술 연산자 * , / , % , + , - ,
- 관계 연산자 < , > , <= , >= , == , ! = ,
- 이항 비트 산술 연산자 & , ^ , | ,
- 조건 연산자 ?: .
|
1)
한 피연산자가 10진 부동 소수점 타입을 가지는 경우, 다른 피연산자는 표준 부동 소수점,
복소수, 또는 허수 타입을 가져서는 안 됩니다.
|
(C23 이후) |
-
- 정수 또는 실수 부동소수점 타입은 long double 으로 변환
| (C99부터) |
-
- 정수 또는 실수 부동소수점 타입은 double 으로 변환
| (C99부터) |
-
- 정수 타입은 float 으로 변환됨 (가능한 유일한 실수 타입은 float이며, 이는 그대로 유지됨)
| (C99부터) |
-
- 타입이 동일한 경우, 해당 타입이 공통 타입이 됩니다.
-
그렇지 않으면 타입이 서로 다릅니다:
- 타입이 동일한 부호 특성을 가지는 경우(둘 다 부호 있음 또는 둘 다 부호 없음), 변환 순위 [1] 가 더 낮은 타입의 피연산자가 다른 타입으로 암시적으로 변환됩니다 [2] .
-
그렇지 않으면 피연산자들의 부호 특성이 다릅니다:
- 부호 없는 타입의 변환 순위 가 부호 있는 타입의 순위보다 크거나 같은 경우, 부호 있는 타입의 피연산자가 부호 없는 타입으로 암시적으로 변환됩니다.
-
그렇지 않으면 부호 없는 타입의
변환 순위
가 부호 있는 타입보다 낮습니다:
- 부호 있는 타입이 부호 없는 타입의 모든 값을 표현할 수 있는 경우, 부호 없는 타입의 피연산자가 부호 있는 타입으로 암시적으로 변환됩니다.
- 그렇지 않으면, 두 피연산자 모두 부호 있는 피연산자의 타입에 대응하는 부호 없는 타입으로 암시적 변환을 겪습니다.
- ↑ 순위 규칙은 아래 정수 승격 을 참조하십시오.
- ↑ 아래 암시적 변환 의미론 에서 "정수 변환"을 참조하십시오.
1.f + 20000001; // int가 float로 변환되어 20000000.00이 됨 // 덧셈 후 float로 반올림하여 20000000.00이 됨 (char)'a' + 1L; // 먼저, char 'a'(97)가 int로 승격됨 // 다른 타입: int와 long // 같은 부호성: 둘 다 부호 있음 // 다른 순위: long이 int보다 높은 순위 // 따라서 int 97은 long 97로 변환됨 // 결과는 97 + 1 = 98, 타입은 signed long 2u - 10; // 다른 타입: unsigned int와 signed int // 다른 부호성 // 같은 순위 // 따라서 signed int 10은 unsigned int 10으로 변환됨 // 산술 연산이 unsigned 정수로 수행되므로 // ("Arithmetic operators" 항목 참조), 계산은 (2 - 10) // 모듈로 (2의 n승), 여기서 n은 unsigned int의 값 비트 수 // unsigned int가 32비트이고 객체 표현에 패딩 비트가 없다면 // 결과는 (-8) 모듈로 (2의 32승) = 4294967288 // 타입은 unsigned int 5UL - 2ULL; // 다른 타입: unsigned long과 unsigned long long // 같은 부호성 // 다른 순위: unsigned long long의 순위가 더 높음 // 따라서 unsigned long 5는 unsigned long long 5로 변환됨 // 산술 연산이 unsigned 정수로 수행되므로 // ("Arithmetic operators" 항목 참조), // unsigned long long이 64비트라면 // 결과는 (5 - 2) 모듈로 (2의 64승) = 3, 타입은 // unsigned long long 0UL - 1LL; // 다른 타입: unsigned long과 signed long long // 다른 부호성 // 다른 순위: signed long long의 순위가 더 높음 // ULONG_MAX > LLONG_MAX인 경우, signed long long은 모든 // unsigned long을 표현할 수 없으므로, 이는 마지막 경우: 두 피연산자는 모두 // unsigned long long으로 변환됨 unsigned long 0은 unsigned long long 0으로 변환됨 // long long 1은 unsigned long long 1로 변환됨 산술 연산이 // unsigned 정수로 수행되므로 // ("Arithmetic operators" 항목 참조), // unsigned long long이 64비트라면 // 계산은 (0 - 1) 모듈로 (2의 64승) // 따라서 결과는 18446744073709551615 (ULLONG_MAX), 타입은 // unsigned long long
|
결과 타입은 다음과 같이 결정됩니다:
double complex z = 1 + 2*I; double f = 3.0; z + f; // z는 그대로 유지되고, f는 double로 변환되며, 결과는 double complex입니다 |
(C99부터) |
언제나 그렇듯, 부동 소수점 연산자의 결과는 해당 타입이 나타내는 범위와 정밀도보다 더 넓은 범위와 정밀도를 가질 수 있습니다 (참조: FLT_EVAL_METHOD ).
|
참고: 실수 및 허수 피연산자는 복소수로 암시적으로 변환되지 않습니다. 이렇게 하면 추가 계산이 필요하게 되며, 무한대, NaN 및 부호 있는 0이 포함된 특정 경우에서 바람직하지 않은 결과를 생성하기 때문입니다. 예를 들어, 실수가 복소수로 변환된다면 2.0×(3.0+i∞)는 (2.0+i0.0)×(3.0+i∞) ⇒ (2.0×3.0–0.0×∞) + i(2.0×∞+0.0×3.0) ⇒ NaN+i∞로 계산되어 올바른 결과인 6.0+i∞ 대신 잘못된 결과가 나옵니다. 허수가 복소수로 변환된다면 i2.0×(∞+i3.0)는 (0.0+i2.0) × (∞+i3.0) ⇒ (0.0×∞ – 2.0×3.0) + i(0.0×3.0 + 2.0×∞) ⇒ NaN + i∞로 계산되어 올바른 결과인 –6.0 + i∞ 대신 잘못된 결과가 나옵니다. |
(C99부터) |
참고: 일반적인 산술 변환과 관계없이, 계산은 항상 다음 규칙에 따라 지정된 것보다 좁은 타입에서 수행될 수 있습니다. as-if 규칙 에 따르면.
값 변환
Lvalue 변환
모든 lvalue 표현식 은 배열 타입이 아닌 모든 타입에 대해, 다음을 제외한 모든 컨텍스트에서 사용될 때
- 주소 연산자 의 피연산자로 사용될 때 (허용되는 경우),
- 전위/후위 증가 및 감소 연산자 의 피연산자로 사용될 때,
- 멤버 접근 (점) 연산자의 좌측 피연산자로 사용될 때,
- 대입 및 복합 대입 연산자의 좌측 피연산자로 사용될 때,
-
sizeof의 피연산자로 사용될 때,
lvalue 변환
을 거칩니다: 타입은 동일하게 유지되지만,
const
/
volatile
/
restrict
-한정자 및
atomic
속성이 있는 경우 이를 상실합니다. 값은 동일하게 유지되지만, lvalue 속성을 상실합니다(주소를 더 이상 취할 수 없음).
lvalue가 불완전한 타입을 가질 경우, 동작은 정의되지 않습니다.
lvalue가 주소가 한 번도 취해지지 않은 자동 저장 기간 객체를 지정하고, 해당 객체가 초기화되지 않은 경우(초기화자로 선언되지 않았고 사용 전까지 할당이 수행되지 않음), 그 동작은 정의되지 않습니다.
이 변환은 객체의 값이 해당 위치에서 메모리 로드되는 방식을 모델링합니다.
volatile int n = 1; int x = n; // n에 대한 lvalue 변환으로 n의 값을 읽음 volatile int* p = &n; // lvalue 변환 없음: n의 값을 읽지 않음
배열에서 포인터로의 변환
배열 타입의 lvalue expression (until C99) expression (since C99) 는 다음의 경우를 제외하고 사용될 때
- 주소 연산자 의 피연산자로 사용될 때,
-
sizeof의 피연산자로 사용될 때, -
typeof및typeof_unqual(C23부터) 의 피연산자로 사용될 때, - 배열 초기화 에 사용되는 문자열 리터럴로 사용될 때,
첫 번째 요소에 대한 비-좌측값 포인터로 변환을 겪습니다.
배열이
register
로 선언된 경우, 동작은 정의되지 않습니다.
비-좌측값 배열 또는 그 어떤 요소도 접근할 수 없습니다 (C99까지) , temporary lifetime 을 가집니다 (C99부터) .
int a[3], b[3][4]; int* p = a; /* &a[0]로의 변환 */ int (*q)[4] = b; /* &b[0]로의 변환 */ struct S { int a[1]; }; struct S f(void) { struct S result = {{0}}; /* C99 이후 {0} */ return result; } void g(void) { int* p = f().a; /* C99 이전 오류; C99 이후 정상 */ int n = f().a[0]; /* C99 이전 오류; C99 이후 정상 */ f().a[0] = 13; /* C99 이전 오류; C99 이후 미정의 동작 */ (void)p, (void)n; } int main(void) { return 0; }
함수에서 포인터로의 변환
함수 지정자 표현식은 다음을 제외한 어떤 문맥에서 사용될 때
- 주소 연산자 의 피연산자로 사용될 때,
-
sizeof의 피연산자로 사용될 때, -
typeof및typeof_unqual(C23부터) 의 피연산자로 사용될 때,
식으로 지정된 함수에 대한 비좌측값 포인터로의 변환을 겪습니다.
int f(int); int (*p)(int) = f; // f로의 변환 (***p)(1); // f에 대한 반복 역참조 및 &f로의 변환
암시적 변환 의미론
암시적 변환은 할당에 의한 것처럼 또는 일반적인 산술 변환 인지 여부에 관계없이 두 단계로 구성됩니다:
호환 가능한 타입
모든 유형의 값을 호환 가능한 유형 으로의 변환은 항상 no-op이며 표현을 변경하지 않습니다.
uint8_t (*a)[10]; // uint8_t가 unsigned char에 대한 typedef인 경우 unsigned char (*b)[] = a; // 이 포인터 타입들은 호환됩니다
정수 승격
정수 승격은 int의 순위 보다 작거나 같은 순위를 가진 임의의 정수 타입 값이나 비트 필드 타입 _Bool (C23까지) bool (C23부터) , int , signed int , unsigned int 의 값을 int 또는 unsigned int 타입의 값으로 암시적으로 변환하는 것입니다.
만약 int 가 원본 타입의 전체 값 범위(또는 원본 비트 필드의 값 범위)를 표현할 수 있다면, 값은 int 타입으로 변환됩니다. 그렇지 않으면 값은 unsigned int 로 변환됩니다.
|
비트 정밀 정수 타입의 비트 필드에서 가져온 값은 해당 비트 정밀 정수 타입으로 변환됩니다. 그렇지 않으면, 비트 정밀 정수 타입은 정수 승격 규칙에서 제외됩니다. |
(C23부터) |
정수 승격은 부호를 포함한 값을 보존합니다:
int main(void) { void f(); // 구식 함수 선언 // C23부터 void f(...)는 승환(promotions)에 대해 동일한 동작을 가짐 char x = 'a'; // int에서 char로의 정수 변환 f(x); // char에서 다시 int로의 정수 승환 } void f(x) int x; {} // 함수는 int를 기대함
rank 는 모든 정수 타입 의 속성이며 다음과 같이 정의됩니다:
|
8)
비트 정밀 부호 있는 정수 타입의 순위는 더 적은 너비를 가진 표준 정수 타입이나 더 적은 너비를 가진 비트 정밀 정수 타입의 순위보다 커야 한다.
9)
동일한 너비를 가진 확장 정수 타입에 대한 비트 정밀 정수 타입의 순위는 구현에서 정의된다.
|
(C23부터) |
참고: 정수 승격은 오직
- 일반적인 산술 변환 (위 참조)의 일부로,
- 기본 인수 승격 (위 참조)의 일부로,
- 단항 산술 연산자 + 및 - 의 피연산자로,
- 단항 비트 연산자 ~ 의 피연산자로,
- 시프트 연산자 << 및 >> 의 양쪽 피연산자로.
불리언 변환모든 스칼라 타입의 값은 암시적으로 _Bool (C23 이전) bool (C23 이후) 으로 변환될 수 있습니다. 값이 0인 정수 상수 표현식과 비교하여 동일한 값들 (C23 이전) 이 영(산술 타입의 경우), 널(포인터 타입의 경우)이거나 nullptr_t 타입을 가진 값들 (C23 이후) 은 0 (C23 이전) false (C23 이후) 으로 변환되며, 다른 모든 값들은 1 (C23 이전) true (C23 이후) 으로 변환됩니다. bool b1 = 0.5; // b1 == 1 (0.5 converted to int would be zero) bool b2 = 2.0*_Imaginary_I; // b2 == 1 (but converted to int would be zero) bool b3 = 0.0 + 3.0*I; // b3 == 1 (but converted to int would be zero) bool b4 = 0.0 / 0.0; // b4 == 1 (NaN does not compare equal to zero) bool b5 = nullptr; // b5 == 0 (since C23: nullptr is converted to false) |
(C99 이후) |
정수 변환
모든 정수형 타입의 값은 암시적으로 다른 정수형 타입으로 변환될 수 있습니다. 앞서 설명한 승격(promotions)과 불린 변환(boolean conversions)을 제외한 규칙은 다음과 같습니다:
- 대상 타입이 값을 표현할 수 있는 경우, 값은 변경되지 않습니다.
-
그렇지 않고 대상 타입이 unsigned인 경우, 값에서
2
b
(여기서 b 는 대상 타입의 값 비트 수)을 결과가 대상 타입에 맞을 때까지 반복적으로 빼거나 더합니다. 즉, unsigned 정수는 모듈로 연산을 구현합니다. - 그렇지 않고 대상 타입이 signed인 경우, 동작은 구현에 따라 정의됩니다(시그널 발생을 포함할 수 있음).
char x = 'a'; // int → char, 결과는 변경되지 않음 unsigned char n = -123456; // 대상이 부호 없는 타입이므로 결과는 192 (즉, -123456+483*256) signed char m = 123456; // 대상이 부호 있는 타입이므로 결과는 구현에 따라 정의됨 assert(sizeof(int) > -1); // assert 실패: // 연산자 >가 -1을 size_t로 변환을 요청하며, // 대상이 부호 없는 타입이므로 결과는 SIZE_MAX
실수 부동소수점-정수 변환
모든 실수 부동 소수점 유형의 유한 값은 암시적으로 모든 정수 유형으로 변환될 수 있습니다. 위의 불리언 변환에서 다루는 경우를 제외하고 규칙은 다음과 같습니다:
- 소수 부분은 버려집니다(0 방향으로 절사).
-
- 결과 값이 대상 타입으로 표현 가능한 경우, 해당 값이 사용됩니다
- 그렇지 않으면, 동작은 정의되지 않습니다.
int n = 3.14; // n == 3 int x = 1e10; // 32비트 int에 대한 정의되지 않은 동작
모든 정수형의 값은 암시적으로 모든 실수 부동소수점 형식으로 변환될 수 있습니다.
- 값이 대상 타입으로 정확히 표현될 수 있는 경우, 변경되지 않습니다.
- 값이 표현될 수 있지만 정확히 표현될 수 없는 경우, 결과는 가장 가까운 높은 값 또는 가장 가까운 낮은 값 중 구현에서 정의한 선택입니다(단, IEEE 산술이 지원되는 경우 가장 가까운 값으로 반올림됨). 이 경우 FE_INEXACT 가 발생하는지 여부는 명시되지 않습니다.
- 값이 표현될 수 없는 경우, 동작은 정의되지 않습니다(단, IEEE 산술이 지원되는 경우 FE_INVALID 가 발생하고 결과 값은 명시되지 않음).
이 변환의 결과는 대상 타입이 나타내는 것보다 더 넓은 범위와 정밀도를 가질 수 있습니다 ( FLT_EVAL_METHOD 참조).
부동 소수점에서 정수 변환 시 FE_INEXACT 제어가 필요한 경우, rint 및 nearbyint 함수를 사용할 수 있습니다.
double d = 10; // d = 10.00 float f = 20000001; // f = 20000000.00 (FE_INEXACT) float x = 1 + (long long)FLT_MAX; // 정의되지 않은 동작
실수 부동소수점 변환
모든 실수 부동 소수점 타입의 값은 다른 실수 부동 소수점 타입으로 암시적으로 변환될 수 있습니다.
- 값이 대상 타입으로 정확히 표현될 수 있는 경우, 변경되지 않습니다.
- 값이 표현될 수 있지만 정확히 표현할 수 없는 경우, 결과는 가장 가까운 높은 값 또는 가장 가까운 낮은 값이 됩니다(즉, 반올림 방향은 구현에 따라 정의됨). 단 IEEE 연산이 지원되는 경우 가장 가까운 값으로 반올림됩니다.
-
값이 표현될 수 없는 경우, 동작은 정의되지 않음
.이 섹션은 불완전합니다
이유: 적절하게 부호화된 무한대가 필요한지 IEEE 확인 필요
이 변환의 결과는 대상 타입이 나타내는 것보다 더 넓은 범위와 정밀도를 가질 수 있습니다 ( FLT_EVAL_METHOD 참조).
double d = 0.1; // d = 0.1000000000000000055511151231257827021181583404541015625 float f = d; // f = 0.100000001490116119384765625 float x = 2 * (double)FLT_MAX; // 정의되지 않음
복소수 타입 변환모든 복소수 타입의 값은 다른 복소수 타입으로 암시적으로 변환될 수 있습니다. 실수부와 허수부는 각각 실수 부동소수점 타입에 대한 변환 규칙을 따릅니다. 허수 타입 변환모든 허수 타입의 값은 다른 허수 타입으로 암시적으로 변환될 수 있습니다. 허수부는 실수 부동소수점 타입에 대한 변환 규칙을 따릅니다. double imaginary d = 0.1*_Imaginary_I; float imaginary f = d; // f is 0.100000001490116119384765625*I 실수-복소수 변환모든 실수 부동소수점 타입의 값은 모든 복소수 타입으로 암시적으로 변환될 수 있습니다.
모든 복소수 타입의 값은 모든 실수 부동소수점 타입으로 암시적으로 변환될 수 있습니다.
참고: 복소수에서 실수로의 변환에서 허수부의 NaN은 실수 결과로 전파되지 않습니다. double complex z = 0.5 + 3*I; float f = z; // the imaginary part is discarded, f is set to 0.5 z = f; // sets z to 0.5 + 0*I 실수-허수 변환모든 허수 타입의 값은 모든 실수 타입(정수 또는 부동소수점)으로 암시적으로 변환될 수 있습니다. 대상 타입이 _Bool (C23 이전) bool (C23 이후) 인 경우를 제외하고 결과는 항상 양의(또는 부호 없는) 영입니다. 이 경우 부울 변환 규칙이 적용됩니다. 모든 실수 타입의 값은 모든 허수 타입으로 암시적으로 변환될 수 있습니다. 결과는 항상 양의 허수 영입니다. double imaginary z = 3*I; bool b = z; // Boolean conversion: sets b to true float f = z; // Real-imaginary conversion: sets f to 0.0 z = 3.14; // Imaginary-real conversion: sets z to 0*_Imaginary_I 복소수-허수 변환모든 허수 타입의 값은 모든 복소수 타입으로 암시적으로 변환될 수 있습니다.
모든 복소수 타입의 값은 모든 허수 타입으로 암시적으로 변환될 수 있습니다.
double imaginary z = I * (3*I); // the complex result -3.0+0i loses real part // sets z to 0*_Imaginary_I |
(C99 이후) |
포인터 변환
객체 타입에 대한 모든 포인터로부터 다음 의미론을 통해 암시적으로 변환될 수 있는 void 포인터:
- 객체에 대한 포인터가 void 포인터로 변환된 후 다시 원래 포인터로 변환되면, 그 값은 원본 포인터와 동일하게 비교됩니다.
- 다른 보장은 제공되지 않습니다.
int* p = malloc(10 * sizeof(int)); // malloc은 void*를 반환합니다
비한정 타입에 대한 포인터는 해당 타입의 한정된 버전에 대한 포인터로 암시적으로 변환될 수 있습니다(다시 말해,
const
,
volatile
, 그리고
restrict
한정자를 추가할 수 있습니다). 원본 포인터와 결과 포인터는 비교 시 동일합니다.
int n; const int* p = &n; // &n은 int* 타입을 가짐
값이 0 인 모든 정수 상수 표현식 과 함께, 값이 0인 정수 포인터 표현식을 void * 타입으로 캐스팅한 것은 모든 포인터 타입(객체 포인터와 함수 포인터 모두)으로 암시적으로 변환될 수 있습니다. 결과는 해당 타입의 널 포인터 값이며, 해당 타입의 어떤 널이 아닌 포인터 값과도 비교 시 같지 않음이 보장됩니다. 이러한 정수 또는 void * 표현식을 널 포인터 상수 라고 하며, 표준 라이브러리는 이 상수의 한 정의를 매크로 NULL 로 제공합니다.
int* p = 0; double* q = NULL;
참고 사항
부호 있는 정수 오버플로는 모든 산술 연산자에서 정의되지 않은 동작이지만, 정수 변환에서 부호 있는 정수 형식의 오버플로는 단순히 지정되지 않은 동작입니다.
반면, 모든 산술 연산자(및 정수 변환)에서 부호 없는 정수 오버플로는 잘 정의된 연산이며 모듈로 연산 규칙을 따르지만, 부동 소수점에서 정수 변환에서 부호 없는 정수 오버플로는 정의되지 않은 동작입니다: 부호 없는 정수로 변환될 수 있는 실수 부동 소수점 타입의 값은 개구간
(
-1
,
Unnn_MAX
+ 1
)
에 속하는 값들입니다.
unsigned int n = -1.0; // 정의되지 않은 동작
포인터와 정수 간 변환( 포인터에서 _Bool (C23까지) bool (C23부터) 로의 변환과 (C99부터) 값이 0인 정수 상수 표현식에서 포인터로의 변환은 제외), 객체에 대한 포인터 간 변환(한쪽이 void 포인터인 경우 제외), 그리고 함수에 대한 포인터 간 변환(함수들이 호환 가능한 타입을 가진 경우 제외)은 절대 암시적으로 이루어지지 않으며 캐스트 연산자 가 필요합니다.
함수 포인터와 객체 포인터( void * 포함) 또는 정수 간에는 (암시적 또는 명시적) 변환이 존재하지 않습니다.
참고문헌
- C23 표준 (ISO/IEC 9899:2024):
-
- 6.3 변환 (p: 44-50)
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.3 변환 (p: 37-41)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.3 변환 (p: 50-56)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.3 변환 (p: 42-48)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 3.2 변환
참고 항목
|
C++ documentation
for
Implicit conversions
|