Új hozzászólás Aktív témák

  • Jester01

    veterán

    válasz !wannabe #2508 üzenetére

    A castolás tulajdonképpen típus ráerőszakolása. Fontos, hogy C-ben ilyenkor (pointerek esetén) nincs semmi konverzió, vagyis a gép elhiszi neked, hogy az a pointer valóban az amire castolod.
    Nagyon rossz példa
    const char *text = "1234";
    int x = *(int*)text;

    Ebben az esetben x nem 1 lesz, hanem az "1234" memória leképezésének int megfelelője. Ez ascii kódban a 0x31 0x32 0x33 0x34 byte sorozatot jelenti, ami 32 bites little-endian rendszerben integerként 0x34333231=875770417. Tehát még csak nem is hasonlít arra, amit szegény kezdő programozó gondolt. (Már ha nem a még rosszabb int x = (int)text; formát próbálta.)

    A castolást lehetőség szerint kerülni kell, de bizonyos esetekben szükséges rossz. Most hirtelen jó példát nem is tudok rá hozni.

    Tipikus hibát viszont igen: ez a void* oda-vissza castolása. Szabvány C-ben erre semmi szükség, mivel a konverzió mind a két irányba automatikus. Példák:
    Rossz
    int *p = (int*)malloc(10 * sizeof(int));
    fwrite((void*)p, sizeof(int), 10, stdout);

    Helyes
    int *p = malloc(10 * sizeof(int));
    fwrite(p, sizeof(int), 10, stdout);

    Bizonyos API függvényekhez viszont szükséges castolni, például a bind ilyen:

    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    Itt az addr argumentum valójában egy sereg struct valamelyike lehet, a címtartománytól függően, például sockaddr_un unix sockethez, sockaddr_in internet sockethez, stb. Ilyenkor castolni kell. Mivel semmi garancia nincs cast esetén, ezért ez semmivel sem jobb mintha az argumentum típusa egyszerűen void* lenne (amihez nem kellene cast), de sajnos a szabványba ez került be. Példa:

    struct sockaddr_un my_addr;
    ...
    my_addr.sun_family = AF_UNIX;
    bind(sfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_un));

    MOD: ja meg az accept is ilyen, azt meg te is használtad ;)

Új hozzászólás Aktív témák