Μετάβαση στο περιεχόμενο

Η C είναι απλή/enum - union - sizeof

Από Βικιβιβλία

Μάθαμε για το typedef, το οποίο φτιάχνει νέους τύπους απλά μετονομάζοντας τον παλιό. Λοιπόν, υπάρχει κι η εντολή "enum", με την οποία μπορούμε να φτιάξουμε νέους τύπους, και νέες τιμές γι' αυτούς! Ας πούμε ότι έχετε ένα τύπο για την κατεύθυνση του ανέμου. Ο άνεμος ας πούμε ότι μπορεί να πηγαίνει νότια-νοτιοδυτικά-νοτιοανατολικά-βόρεια-βορειοδυτικά-βορειοανατολικά-δυτικά-ανατολικά. Αυτό θα μπορούσα να το φτιάξω με μια "enum" έτσι:

enum WindDirection { SOUTH, SOUTH_EAST, SOUTH_WEST, NORTH, NORTH_EAST, NORTH_WEST, WEST, EAST };

/* Μέσα σε κώδικα */
enum WindDirection windDir;

windDir = SOUTH;
windDir = NORTH;

να θυμάστε ότι στην C, τα "enum" μετατρέπονται σε "int" αν βρεθούν μέσα σε οποιαδήποτε αριθμητική/λογική πράξη. Πώς? Έτσι όπως τα έχω δηλώσει, το SOUTH θα είναι μηδέν, το SOUTH_EAST θα είναι ένα κτλ. Μπορείτε να δώσετε συγκεκριμένες τιμές σ' αυτά να ονόματα αν θέλετε, απλά κάνοντας πχ "SOUTH=7", όμως κάθε τιμή μετά από τη τελευταία δηλωμένη θα συνεχίζει ανεβαίνοντας πάντα κατά ένα.

Μάθαμε επίσης για το struct, το οποίο φτιάχνει νέους τύπους μαζεύοντας κάτω απ' το ίδιο όνομα όποιους άλλους θέλουμε. Λοιπόν, το "union" συντάσσεται ακριβώς όπως και το "struct", αλλά έχει μια τεράστια διαφορά: όλα τα διαφορετικά μέλη του βρίσκονται ακριβώς στην ίδια διεύθυνση, και το μέγεθός της είναι το μέγεθος του μεγαλυτέρου απ' όλα μέλους. Σε αντίθεση με την "struct", όπου το μέγεθός της είναι το άθροισμα των μεγεθών όλων των μελών της ( τουλάχιστον ). Χρησιμεύει στην απλούστευση του κώδικα, αποφεύγοντας δηλαδή μακροσκελείς και επιρρεπείς σε λάθη εντολές μετατροπής.

Όσο μιλάω για το μέγεθος, ορίστε ένας τελεστής που επιστρέφει το μέγεθος σε bytes ενός τύπου, "sizeof". Συντάσσεται έτσι:

sizeof τύπος;
/* ή */
sizeof(τύπος);
/* μπορεί να χρησιμοποιηθεί και με μεταβλητές */
int integer;
sizeof(integer);

( λειτουργεί και με πίνακες και με δείκτες, αν και για το δεύτερο ίσως δεν κάνει ότι θέλατε... ) Τέλος, ίσως το sizeof να μην επιστρέψει τα μεγέθη που περιμένατε για μια struct, κι αυτό λόγω ευθυγράμμισης των δεδομένων. Είναι πολύ νωρίς γι' αυτό, απλά σκεφτείτε ότι ένας ακέραιος 32-bit διαβάζεται απ' τη CPU πολύ πιο γρήγορα αν η αρχή του βρίσκεται σε μνήμη η οποία είναι ακέραιο πολλαπλάσιο του 4, για παράδειγμα. ;-)

Ας κάνω ένα παράδειγμα που δείχνει όσα είπα παραπάνω:

#include <stdio.h>

/* Same as:
enum _type { E_CHAR, E_INT, E_FLOAT };
typedef enum _type Type;
*/
typedef enum { E_NONE, E_CHAR, E_INT, E_FLOAT } Type;

typedef union
{
    char c;
    int i;
    float f;
}Data;

typedef struct
{
    Data itsData;

    Type itsType;
}Input;

int main(void)
{
    Input input = { { 0 }, E_NONE };
    char answer;

    printf("What will you type?\n( c for character, i for integer, f for real ) > ");
    scanf(" %c", &answer);

    switch (answer)
    {
        case 'c':
            printf("Type a character: ");
            scanf(" %c", &input.itsData.c);
            input.itsType = E_CHAR;
        break;
        case 'i':
            printf("Type an integer: ");
            scanf("%d", &input.itsData.i);
            input.itsType = E_INT;
        break;
        case 'f':
            printf("Type a real: ");
            scanf("%f", &input.itsData.f);
            input.itsType = E_FLOAT;
        break;
    }

    switch (input.itsType)
    {
        case E_CHAR:
            printf("You typed the character: %c\n", input.itsData.c);
        break;
        case E_INT:
            printf("You typed the integer: %d\n", input.itsData.i);
        break;
        case E_FLOAT:
            printf("You typed the real: %g\n", input.itsData.f);
        break;
    }

    printf("\n"
          "sizeof(char) = %d\n"
          "sizeof(short) = %d\n"
          "sizeof(int) = %d\n"
          "sizeof(long) = %d\n"
          "sizeof(float) = %d\n"
          "sizeof(double) = %d\n"
          "sizeof(long double) = %d\n"
          "sizeof(Type) = %d\n"
          "sizeof(Data) = %d\n"
          "sizeof(Input) = %d\n",
          sizeof(char), sizeof(short), sizeof(int), sizeof(long),
          sizeof(float), sizeof(double), sizeof(long double),
          sizeof(Type), sizeof(Data), sizeof(Input)
          );

    while (getchar() != '\n');
    getchar();

    return 0;
}

Happy coding! :-)