Szukaj…


Składnia

  • Jawna konwersja (inaczej „rzutowanie”): wyrażenie (typ)

Uwagi

Jawna konwersja ” jest również powszechnie nazywana „rzutowaniem”.

Konwersje liczb całkowitych w wywołaniach funkcji

Biorąc pod uwagę, że funkcja ma odpowiedni prototyp, liczby całkowite są rozszerzane dla wywołań funkcji zgodnie z zasadami konwersji liczb całkowitych, C11 6.3.1.3.

6.3.1.3 Liczby całkowite ze znakiem i bez znaku
Gdy wartość z typem całkowitym jest konwertowana na inny typ liczb całkowitych inny niż _Bool, jeśli wartość może być reprezentowana przez nowy typ, pozostaje niezmieniona.

W przeciwnym razie, jeśli nowy typ nie jest podpisany, wartość jest konwertowana przez wielokrotne dodawanie lub odejmowanie wartości większej niż maksymalna wartość, którą można przedstawić w nowym typie, dopóki wartość nie znajdzie się w zakresie nowego typu.

W przeciwnym razie nowy typ jest podpisany i nie można w nim reprezentować wartości; albo wynik jest zdefiniowany w implementacji, albo podniesiony jest sygnał zdefiniowany w implementacji.

Zwykle nie należy obcinać typu z szerokim znakiem do węższego typu, ponieważ oczywiście wartości nie mogą się zmieścić i nie ma wyraźnego znaczenia, że powinien to mieć. Cytowany powyżej standard C definiuje te przypadki jako „zdefiniowane w implementacji”, to znaczy, że nie są przenośne.

Poniższy przykład zakłada, że int ma szerokość 32 bitów.

#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;
}

Konwersje wskaźnika w wywołaniach funkcji

Konwersje wskaźnika na void* są niejawne, ale każda inna konwersja wskaźnika musi być jawna. Podczas gdy kompilator umożliwia jawną konwersję z dowolnego typu wskaźnika do danych na dowolny inny typ wskaźnika do danych, dostęp do obiektu przez źle wpisany wskaźnik jest błędny i prowadzi do nieokreślonego zachowania. Jedyny przypadek, w którym są one dozwolone, to jeśli typy są kompatybilne lub jeśli wskaźnik, z którym patrzysz na obiekt, jest typem znaków.

#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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow