en.cppreference.com/w/c/language/conversion
Implicit conversions - cppreference.com
When an expression is used in the context where a value of a different type is expected, conversion may occur: int n = 1L; // expression 1L has type long, int is expected n = 2.1; // expression 2.1 has type double, int is expected char *p = malloc(10); //
en.cppreference.com
서로 타입이 다른 변수끼리 연산, 대입, 호출, Casting이 이뤄질 때 따로 타입을 명시해주지 않으면 Implicit conversion(묵시적, 암시적 형변환)이 이뤄진다.
이는 컴파일러가 내부 규칙에 따라 변환시켜주는 것이므로 규칙을 어느정도 알고 있어야 의도하지 않은 동작을 막을 수 있다.
* complex number type의 설명은 생략했다.
다음과 같이 용어를 축약하여 사용하였다.
SI: signed int, int
UI: unsigned int
SL: signed long
SC: signed char
UC: unsigned char
LI: long int
LLI: long long int
LD: long double
1. 정수형 변수와 실수형 변수 간 형변환
한 변수는 실수형(float, double)이고 한 변수는 정수형일 때,
실수형 변수가 우선하여 정수형 변수가 실수형으로 변환돼 연산이 이뤄진다.
int < long int < long long int < float < double < long double
printf("%f\n", 1.f + 2000001);
// int인 2000001이 2000001.0로 변한돼 연산이 이뤄지고
// float 형태의 결과 2000002.0가 출력된다.
2. 정수형 변수 간 변환
- (32-bit system 기준) SI보다 작은 정수 타입은 일단 SI로 승격(promotion)된 후 처리된다.
printf("%#x\n", (char)'a' + 1L); // (char)'a' → 97
// 일단 char타입이므로 SI로 승격된다.
// char은 시스템에 따라 signedness가 다른데 (x86은 signed)
// 97=0x61=1b01100001이므로 MSB가 0이어서 signedness에 관계없이
// SI 0x00000061이 된다.
// 1L은 SL 타입이므로 SI vs. SL이고 - (1)
// SL이 더 rank가 높으므로 SI 0x00000061이 SL 0x00000061이 된다.
// SL 98이 연산 결과가 된다.
printf("%#x\n", 2u - 10); // UI 2 와 SI 10의 연산
// UI가 우선하므로 SI 10이 UI 10으로 변환된다. - (3-1)
// 따라서, 2u - 10u 이고 UI 0xfffffff8이 된다.
// 참고로 다음 연산은 경우가 다르다.
printf("%#x\n", 2u + (-10)); // compile error
// 위의 경우와 동일하 변환된 후 연산되어야 하는데, (3-1)
// SI (-10)은 음수이기 때문에 unsigned type으로 변환될 수 없다는
// 컴파일 에러가 발생한다.
unsigned int left = 2u;
int right = -10;
printf("%x\n", left + right); //ok, 0xfffffff8
printf("%#x\n", 5UL - 2ULL);
// same signedness, different rank - (1)
// UL 5가 ULL로 변환되어 ULL 0x3이 출력된다.
// 참고로,
printf("%d\n", sizeof(5UL - 2ULL)); // 8이다.
printf("%llu\n", 0UL - 1LL);
// 일단, signedness가 다른데 SLL이 UL보다 우선한다.
// ULONG_MAX > LLONG_MAX인 경우, SLL이 UL의 모든 수를 다 표현할 수가 없다. - (4)
// 따라서, 두 수 모두 ULL로 변환되고
// 18446744073709551615가 출력된다.
3. Array to pointer
int a[3], b[3][4];
int* p = a; // conversion to &a[0], where a[0] is int;
int (*q)[4] = b; // conversion to &b[0], where b[0] is int [4];
4. Function to pointer
int f(int);
int (*p)(int) = f; // conversion to &f
(***p)(1); // repeated dereference to f and conversion back to &f
'Study > Programming' 카테고리의 다른 글
Endianness (0) | 2020.10.04 |
---|---|
Memory Pool을 이용한 Linked List 구현 (0) | 2020.09.26 |
댓글