수색…


통사론

  • 명시 적 변환 (일명 "캐스팅") : (유형) 표현식

비고

" 명시 적 변환 "은 일반적으로 "캐스팅"이라고도합니다.

함수 호출에서의 정수 변환

함수에 적절한 프로토 타입이 주어지면 정수 변환 규칙에 따라 함수 호출에 대한 정수가 확장됩니다 (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;
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow