Προς το περιεχόμενο

Data structure alignment - C


dimitris21gr

Προτεινόμενες αναρτήσεις

Καλησπέρα στο φόρουμ,

 

Διαβάζοντας Link.png Site: αυτό άρθρο στο wikipedia θα ήθελα να ρωτήσω το εξής.

 

Στα πλαίσια της άσκησης που κάνω θέλω να φτιάξω ένα struct το οποίο να περιέχει 3 char μεταβλητές. Με δοκιμές που κάνω βλέπω πως όντως το μέγεθος του είναι 3 bytes. Βάση και του παραπάνω άρθρου μπορώ να βγάλω το ασφαλές συμπέρασμα ότι όπου και να τρέξω το πρόγραμμα μου το struct αυτό θα έχει 3 bytes μέγεθος;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 31
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοφιλείς Ημέρες

Καλησπέρα στο φόρουμ,

 

Διαβάζοντας Link.png Site: αυτό άρθρο στο wikipedia θα ήθελα να ρωτήσω το εξής.

 

Στα πλαίσια της άσκησης που κάνω θέλω να φτιάξω ένα struct το οποίο να περιέχει 3 char μεταβλητές. Με δοκιμές που κάνω βλέπω πως όντως το μέγεθος του είναι 3 bytes. Βάση και του παραπάνω άρθρου μπορώ να βγάλω το ασφαλές συμπέρασμα ότι όπου και να τρέξω το πρόγραμμα μου το struct αυτό θα έχει 3 bytes μέγεθος;

 

Εμ! όταν δεν τα μαθαίνεις από ΑΕΙ και μαθαίνεις προγραμματισμό από Google, τέτοιες ερωτήσεις κάνεις...

Κανένα θέμα με σένα φίλε μου :P σε άλλους τα λέω :P


 

Λοιπόν, ο χαρακτήρας σε όλα τα λειτουργικά και όλες τις αρχητεκτονικές (32, 64bit) έχει το ίδιο μέγεθος. 1Byte. Οπότε πήρες την απάντησή σου.

 

Άλλοι τύποι μεταβλητών μπορεί να διαφέρουν... πχ o Float στα Windows είναι bydefault 4Byte ενώ σε ότι Unix-οιδες είναι 8. Ρώτα τη Microsoft Γιατί. (Αλλάζει πάντως!)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Για να το καταλάβω και λίγο καλύτερα. Εφόσον στο struct έχω μόνο chars (στην περίπτωση μου 3) πάντα θα γίνεται 1-byte alignment οπότε το μέγεθος του struct θα είναι ίσο με το μέγεθος των μεταβλητών που το αποτελούν;

 

Με είχε προβληματίσει και παλιότερα αυτό το θέμα όμως δεν το έψαξα τόσο διότι δεν με απασχολούσε σε αυτό που έκανα. Αυτήν την φορά όμως με νοιάζει.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Κοίταξε. Τα δεδομένα πρέπει να είναι aligned στη μνήμη. Για να γίνει αυτό με το struct πρέπει αφενώς τα περιεχόμενα του struct να είναι aligned μέσα στο ίδιο struct. Μέσα στο ίδιο struct τα δεδομένα γίνονται aligned στο μέγεθος του μεγαλύτερου τύπου που υπάρχει στο struct. Πχ εσύ έχει 3 χαρακτήρες, 1 B ο καθένας, οπότε τα δεδομένα γίνονται aligned στο μέγεθος ενός χαρακτήρα. Αν είχες 3 χαρακτηρες κι έναν ακέραιο (έστω 4 Β, τότε τα δεδομένα θα έπρεπε να είναι aligned στα 4 Β. Αυτό γίνεται με τη μέθοδο του padding. Ο compiler προσθέτει άχρηστη μνήμη ώστε να γεμίσει τα κενά που απαιτεί το alignment policy.

 

πχ.

struct {
    char a;  // 1 bytes
    char b;  // 1 bytes
    char c;  // 1 bytes
    int  d;  // 4 bytes
}

γίνεται:

struct {
    char a;  // 1 bytes
    char b;  // 1 bytes
    char c;  // 1 bytes
    padding_sizeof_1_byte;
    int  d;  // 4 bytes
}
κι έτσι το τελικό struct έχει μέγεθος 8

Δοκίμασε μία να μετρήσεις μέγεθος από:

struct {
    char a;  // 1 bytes
    char b;  // 1 bytes
    char c;  // 1 bytes
    int  d;  // 4 bytes
}

και από αυτό:

struct {
    char a;  // 1 bytes
    char b;  // 1 bytes
    int  d;  // 4 bytes
    char c;  // 1 bytes
}

Μπορείς να μαντέψεις τι θα συμβεί;
Τι μαθαίνουμε από αυτό το παράδειγμα;

Επίσης ένα struct πρέπει να είναι aligned στη μνήμη. Αν είχε έναν πίνακα από structs τότε πρέπει τα στοιχεία του να είναι aligned. Οπότε εκεί πρέπει να μπει, αν χρειάζεται έξτρα padding.

 

Κάπου ανέφερα κάτι για padding policies. Αυτόν τον ορισμό δεν τον έχω δει κάπου. Τώρα μου κατέβηκε και με αυτό ήθελα να πω πως ανάλογα με τον compiler που χρησιμοποιείς, τότε μπορεί να δεις διαφορετικά αποτελέσματα. Για παράδειγμα κάποιος compiler μπορεί από default να κάνει align στα 4 B. Δηλαδή το παράδειγμα με τους τρεις χαρακτήρες θα υποστεί padding και θα έχει μέγεθος 4 B. Αυτά βέβαια είναι ρυθμίσεις και τις αλλάζεις από τα options του κάθε compiler.

 

 

UPDATE:

Ρίξε μία ματιά εδώ σε ένα παλιότερο θέμα μου.

  • Like 3
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Για να το καταλάβω και λίγο καλύτερα. Εφόσον στο struct έχω μόνο chars (στην περίπτωση μου 3) πάντα θα γίνεται 1-byte alignment οπότε το μέγεθος του struct θα είναι ίσο με το μέγεθος των μεταβλητών που το αποτελούν;

 

Με είχε προβληματίσει και παλιότερα αυτό το θέμα όμως δεν το έψαξα τόσο διότι δεν με απασχολούσε σε αυτό που έκανα. Αυτήν την φορά όμως με νοιάζει.

 

 

Το θέμα είναι γιατί σε νοιάζει....

 

Θα μπορούσες να το μοιραστείς; Θαρρώ πως η απάντηση στην ερώτησή μου θα έχει περισσότερο ενδιαφέρον και όφελος για εσένα. 

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το θέμα είναι γιατί σε νοιάζει....

 

Θα μπορούσες να το μοιραστείς; Θαρρώ πως η απάντηση στην ερώτησή μου θα έχει περισσότερο ενδιαφέρον και όφελος για εσένα. 

 

Θέλω να διαβάσω μια εικόνα RGB (raw format) σε C και να την αποθηκεύσω κάπως στην μνήμη. Οπότε σκέφτομαι να φτιάξω ένα struct το οποίο θα περιέχει 3 unsigned chars για κάθε χρώμα και έπειτα να φτιάξω ένα 2d πίνακα από τέτοια structs ώστε να αποθηκεύσω την πληροφορία τις εικόνας.

Το να γνωρίζω ότι το μέγεθος αυτού του struct είναι πάντα 3 με βοηθάει στο να διαβάσω σχετικά γρήγορα την εικόνα κάνοντας h επαναλήψεις και σε κάθε επανάληψη να γράφω πληροφορία σε μια γραμμή του πίνακα μεγέθους 3 * w, όπου h και w το ύψος και πλάτος της φωτογραφίας αντίστοιχα. Έπειτα, αφού επεξεργαστώ τον πίνακα, πρέπει να αποθηκεύσω σε αρχείο raw την νέα εικόνα που προκύπτει.

 

EDIT: Έχω ήδη υλοποιήσει το παραπάνω σκεπτικό και δουλεύει όμως φοβάμαι μήπως σε άλλη αρχιτεκτονική δεν δουλεύει σωστά.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Θέλω να διαβάσω μια εικόνα RGB (raw format) σε C και να την αποθηκεύσω κάπως στην μνήμη. Οπότε σκέφτομαι να φτιάξω ένα struct το οποίο θα περιέχει 3 unsigned chars για κάθε χρώμα και έπειτα να φτιάξω ένα 2d πίνακα από τέτοια structs ώστε να αποθηκεύσω την πληροφορία τις εικόνας.

Το να γνωρίζω ότι το μέγεθος αυτού του struct είναι πάντα 3 με βοηθάει στο να διαβάσω σχετικά γρήγορα την εικόνα κάνοντας h επαναλήψεις και σε κάθε επανάληψη να γράφω πληροφορία σε μια γραμμή του πίνακα μεγέθους 3 * w, όπου h και w το ύψος και πλάτος της φωτογραφίας αντίστοιχα. Έπειτα, αφού επεξεργαστώ τον πίνακα, πρέπει να αποθηκεύσω σε αρχείο raw την νέα εικόνα που προκύπτει.

 

EDIT: Έχω ήδη υλοποιήσει το παραπάνω σκεπτικό και δουλεύει όμως φοβάμαι μήπως σε άλλη αρχιτεκτονική δεν δουλεύει σωστά.

Τότε χρησιμοποιήσε αυτό ή αυτό. Θα πρότεινα το πρώτο. Επίσης, δε πιστεύω να σε επηρεάσει η αρχιτεκτονική από πίσω αν χρησιμοποιήσεις το πρώτο. Διάβασε από εδώ.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καλησπέρα στο φόρουμ,

 

Διαβάζοντας Link.png Site: αυτό άρθρο στο wikipedia θα ήθελα να ρωτήσω το εξής.

 

Στα πλαίσια της άσκησης που κάνω θέλω να φτιάξω ένα struct το οποίο να περιέχει 3 char μεταβλητές. Με δοκιμές που κάνω βλέπω πως όντως το μέγεθος του είναι 3 bytes. Βάση και του παραπάνω άρθρου μπορώ να βγάλω το ασφαλές συμπέρασμα ότι όπου και να τρέξω το πρόγραμμα μου το struct αυτό θα έχει 3 bytes μέγεθος;

 

 

Θες extension του compiler για αυτη την δουλεια. Δεν ειναι τιποτα, googlare <compiler> struct alignment

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Θες extension του compiler για αυτη την δουλεια. Δεν ειναι τιποτα, googlare <compiler> struct alignment

Extension εννοείς για packing ? Όλα τα ABI δεν ορίζουν alignment 1 για τον char ? Χρειάζεται να κάνει pack ?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καλησπέρα στο φόρουμ,

 

Διαβάζοντας Link.png Site: αυτό άρθρο στο wikipedia θα ήθελα να ρωτήσω το εξής.

 

Στα πλαίσια της άσκησης που κάνω θέλω να φτιάξω ένα struct το οποίο να περιέχει 3 char μεταβλητές. Με δοκιμές που κάνω βλέπω πως όντως το μέγεθος του είναι 3 bytes. Βάση και του παραπάνω άρθρου μπορώ να βγάλω το ασφαλές συμπέρασμα ότι όπου και να τρέξω το πρόγραμμα μου το struct αυτό θα έχει 3 bytes μέγεθος;

 

Όχι, το συμπέρασμα αυτό δε μπορεί να βγει. Εξάλλου το standard είναι σαφέστατο (το τι δεν υπόσχεται λάμπει δια της απουσίας του), π.χ. μερικά από τα πιο ζουμερά σχετικά τμήματα είναι

 

Complete object types have alignment requirements which place restrictions on the addresses at which objects of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated.

 

The alignment requirement of a complete type can be queried using an _Alignof expression. The types char, signed char, and unsigned char shall have the weakest alignment requirement

 

Each non-bit-field member of a structure or union object is aligned in an implementationdefined manner appropriate to its type.

 

Δεν λέει πουθενά ότι το alignof(char) πρέπει να είναι 1, αν και στην πράξη αυτό θα συμβεί "σχεδόν πάντα".

 

Αυτό που θα μπορούσες να κάνεις είναι να βάλεις ένα static assert που αν εντοπίσει ότι alignof(char) > 1 να αποτύχει το compile για να είσαι εξασφαλισμένος ότι η αποτυχία θα πάρει τη μορφή που εσύ επιλέγεις.

 

Προσωπικά δε νομίζω ότι έχει και πολύ νόημα να ασχοληθείς πολύ για το συγκεκριμένο. Ακόμα και σε μια υποτιθέμενη μυστήρια αρχιτεκτονική που χαλάει το γλυκό πρόβλημα θα υπάρξει μόνο αν α) κάποιος πάει να κάνει compile from source και ταυτόχρονα β) ο κώδικάς σου στο σύνολό του θα είναι κατά τα άλλα 100% portable και platform-agnostic -- υπενθυμίζω αυτό καλύπτει και μια υποτιθέμενη μυστήρια αρχιτεκτονική που πιθανότατα δεν έχεις συναντήσει ποτέ σου.

 

Βασικά δηλαδή καλά κάνεις και ψάχνεσαι, αλλά πρακτικά κάπου πρέπει να βάλεις μια τελεία.

 

Εμ! όταν δεν τα μαθαίνεις από ΑΕΙ και μαθαίνεις προγραμματισμό από Google, τέτοιες ερωτήσεις κάνεις...

Κανένα θέμα με σένα φίλε μου :P σε άλλους τα λέω :P


 

Λοιπόν, ο χαρακτήρας σε όλα τα λειτουργικά και όλες τις αρχητεκτονικές (32, 64bit) έχει το ίδιο μέγεθος. 1Byte. Οπότε πήρες την απάντησή σου.

 

Άλλοι τύποι μεταβλητών μπορεί να διαφέρουν... πχ o Float στα Windows είναι bydefault 4Byte ενώ σε ότι Unix-οιδες είναι 8. Ρώτα τη Microsoft Γιατί. (Αλλάζει πάντως!)

 

Sorry που σου το χαλάω αλλά δεν κατάλαβες καν την ερώτηση.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Όχι, το συμπέρασμα αυτό δε μπορεί να βγει. Εξάλλου το standard είναι σαφέστατο (το τι δεν υπόσχεται λάμπει δια της απουσίας του), π.χ. μερικά από τα πιο ζουμερά σχετικά τμήματα είναι

 

Δεν λέει πουθενά ότι το alignof(char) πρέπει να είναι 1, αν και στην πράξη αυτό θα συμβεί "σχεδόν πάντα".

Όσον αφορά το πρότυπο, είναι implementation-defined όπως λέει το quote που έδωσες. Είναι μια λεπτομέρεια που δεν απασχολεί το πρότυπο. Απασχολεί όμως το ABI μιας αρχιτεκτονικής το οποίο δεσμεύει τον implementor. Εννοείται πως δεν μπορώ να γνωρίζω τι γίνεται παντού αλλά με λίγο ψάξιμο που έκανα, τουλάχιστον στα X86, X86_64, SPARC *, MIPS *, ARM (δεν θυμάμαι τι arm) ABIs, αναφέρεται alignment 1 οπότε λογικά ο compiler θα πρέπει να μην εισάγει κανένα padding.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Extension εννοείς για packing ? Όλα τα ABI δεν ορίζουν alignment 1 για τον char ? Χρειάζεται να κάνει pack ?

Όταν έχεις να κανείς με μνήμες, ναι θες packing για να είσαι 100% σίγουρος ότι το τάδε ελεμεντ έχει το τάδε μέγεθος και είναι στο τάδε όφσετ.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ευχαριστώ πάρα πολύ για τις απαντήσεις παιδιά. Καμιά φορά τρώω κάτι τέτοια κολλήματα και προβληματίζομαι με τις ώρες. Απλά δεν μπορώ να σκεφτώ κάτι πιο αποδοτικό για αυτό που θέλω να κάνω, οπότε ψάχνομαι.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ωραίο application για συζήτηση. 

 

Αν και δεν είμαι του image processing, θα πρότεινα buffers ή incomplete structs. 

 

Καταρχάς, με το 2D array χάνεις το continuous allocation στην μνήμη, εάν πας με δήλωση [][]. Επίσης, το size; Θα το μεταφέρεις σε call; Και τι γίνεται εάν θέλεις μόνο το  ένα χρώμα; Κάνεις loop σε όλη την εικόνα και βγάζεις μόνο το R (π.χ.) ;

 

Με incomplete structs μπορείς να έχεις παραπάνω data plus τα actual data για την συνιστώσα που θέλεις. Και το ίδιο structure μπορείς να το κάνεις apply και σε άλλα format εικόνας (π.χ. συμπληρώματα). 

 

Αυτό που προτείνω είναι:

 

 

struct {
  char[3] typeOfData; // π.χ. R, Yr ή ό,τι άλλο
  short int size;
  char* data;
} imgComponentdata, *imgComponentdata;

 

 

Και έτσι, σε μετέπειτα δομή μπορείς να έχεις το component σου... κρατώντας και σημασιολογικά την δομή των raw data. 

 

Π.χ.

 

 

struct {
  int amountOfComponents; // Πόσα components έχει; 
  int typeOfComponent; // Π.χ. 001 , το οποίο είναι ίσο με R π.χ.
  imgComponentData data; 
}
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...