C Language
암시 적 및 명시 적 변환
수색…
통사론
- 명시 적 변환 (일명 "캐스팅") : (유형) 표현식
비고
" 명시 적 변환 "은 일반적으로 "캐스팅"이라고도합니다.
함수 호출에서의 정수 변환
함수에 적절한 프로토 타입이 주어지면 정수 변환 규칙에 따라 함수 호출에 대한 정수가 확장됩니다 (C11). 6.3.1.3.
6.3.1.3 부호있는 및 부호없는 정수
정수 유형의 값이 _Bool이 아닌 다른 정수 유형으로 변환 될 때 값이 새 유형으로 표시 될 수 있으면 변경되지 않습니다.그렇지 않으면 새 유형이 부호가없는 경우 값이 새 유형의 | 위 내에있을 때까지 새 유형에서 표시 할 수있는 최대 값을 하나씩 더] 복적으로 더하거나 빼서 값을 변환합니다.
그렇지 않으면 새 유형이 서명되고 값을 표현할 수 없습니다. 결과가 구현 정의 또는 구현 정의 신호가 발생합니다.
분명히 값이 적합하지 않고 명확한 의미가 없기 때문에 일반적으로 너비가 넓은 서명 된 유형을 더 좁은 서명 된 유형으로 잘라서는 안됩니다. 위에서 인용 한 C 표준은 이러한 사례를 "구현 정의"로 정의합니다. 즉, 이식 할 수 없습니다.
다음 예제에서는 int
가 32 비트 폭이라고 가정합니다.
#include <stdio.h>
#include <stdint.h>
void param_u8(uint8_t val) {
printf("%s val is %d\n", __func__, val); /* val is promoted to int */
}
void param_u16(uint16_t val) {
printf("%s val is %d\n", __func__, val); /* val is promoted to int */
}
void param_u32(uint32_t val) {
printf("%s val is %u\n", __func__, val); /* here val fits into unsigned */
}
void param_u64(uint64_t val) {
printf("%s val is " PRI64u "\n", __func__, val); /* Fixed with format string */
}
void param_s8(int8_t val) {
printf("%s val is %d\n", __func__, val); /* val is promoted to int */
}
void param_s16(int16_t val) {
printf("%s val is %d\n", __func__, val); /* val is promoted to int */
}
void param_s32(int32_t val) {
printf("%s val is %d\n", __func__, val); /* val has same width as int */
}
void param_s64(int64_t val) {
printf("%s val is " PRI64d "\n", __func__, val); /* Fixed with format string */
}
int main(void) {
/* Declare integers of various widths */
uint8_t u8 = 127;
uint8_t s64 = INT64_MAX;
/* Integer argument is widened when function parameter is wider */
param_u8(u8); /* param_u8 val is 127 */
param_u16(u8); /* param_u16 val is 127 */
param_u32(u8); /* param_u32 val is 127 */
param_u64(u8); /* param_u64 val is 127 */
param_s8(u8); /* param_s8 val is 127 */
param_s16(u8); /* param_s16 val is 127 */
param_s32(u8); /* param_s32 val is 127 */
param_s64(u8); /* param_s64 val is 127 */
/* Integer argument is truncated when function parameter is narrower */
param_u8(s64); /* param_u8 val is 255 */
param_u16(s64); /* param_u16 val is 65535 */
param_u32(s64); /* param_u32 val is 4294967295 */
param_u64(s64); /* param_u64 val is 9223372036854775807 */
param_s8(s64); /* param_s8 val is implementation defined */
param_s16(s64); /* param_s16 val is implementation defined */
param_s32(s64); /* param_s32 val is implementation defined */
param_s64(s64); /* param_s64 val is 9223372036854775807 */
return 0;
}
함수 호출의 포인터 변환
void*
로의 포인터 변환은 내재적이지만 다른 포인터 변환은 명시 적이어야합니다. 컴파일러는 모든 포인터 간 데이터 형식에서 다른 포인터 간 데이터 형식으로의 명시 적 변환을 허용하지만 잘못 입력 된 포인터를 통해 개체에 액세스하면 오류가 발생하여 정의되지 않은 동작이 발생합니다. 이들이 허용되는 유일한 경우는 유형이 호환 가능하거나 오브젝트를보고있는 포인터가 문자 유형 인 경우입니다.
#include <stdio.h>
void func_voidp(void* voidp) {
printf("%s Address of ptr is %p\n", __func__, voidp);
}
/* Structures have same shape, but not same type */
struct struct_a {
int a;
int b;
} data_a;
struct struct_b {
int a;
int b;
} data_b;
void func_struct_b(struct struct_b* bp) {
printf("%s Address of ptr is %p\n", __func__, (void*) bp);
}
int main(void) {
/* Implicit ptr conversion allowed for void* */
func_voidp(&data_a);
/*
* Explicit ptr conversion for other types
*
* Note that here although the have identical definitions,
* the types are not compatible, and that the this call is
* erroneous and leads to undefined behavior on execution.
*/
func_struct_b((struct struct_b*)&data_a);
/* My output shows: */
/* func_charp Address of ptr is 0x601030 */
/* func_voidp Address of ptr is 0x601030 */
/* func_struct_b Address of ptr is 0x601030 */
return 0;
}