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

Ερωτήσεις για C


capoelo

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

Αν δεν απατώμαι, το στάνταρ έχει αλλάξει και το sizeof(char) δεν περιγράφεται πλέον ως guaranteed equal to 1 byte, αλλά ως guaranteed equal to 1 unit... με το "unit" ορισμένο ώς το μικρότερο δυνατό μέγεθος απεικόνισης, όχι απαραίτητα όμως σε LL... ή κάπως έτσι τέλος πάντων.

 

Ψάξτο αν σε ενδιαφέρει, πρέπει να είναι στο C99 αν δεν κάνω λάθος (αν το βρεις βάλε και ένα link να το έχουμε πρόχειρο :) )

 

Βαριέμαι να ψάξω ολόκληρο το πρότυπο :)

Στην παράγραφο πάντως που περιγράφει τον sizeof τελεστή και τα τρία πρότυπα αναφέρουν το παρακάτω.

The sizeof operator yields the size (in bytes) of its operand. blah blah. When applied to an operand that has type char, unsigned char, or signed char, the result is 1.

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

  • Απαντ. 1,6k
  • Δημ.
  • Τελ. απάντηση

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

Βρήκα αυτό, με ένα γρήγορο googling: http://stackoverflow.com/questions/2215445/are-there-machines-where-sizeofchar-1

 

Ο χαμός του χαμού.

 

Όντως λένε πως sizeof(char) == 1 αλλά επίσης λένε πως ο sizeof operator επιστρέφει πάντα πλήθος bytes... πιάσε το αυγό και κούρευ' το :lol: Νομίζω ο κώδικάς μου δουλεύει ότι και να ισχύει (δεν είμαι σίγουρος όμως, πρέπει να τον ξανακοιτάξω).

 

EDIT:

 

Δίνουν κι αυτά τα 2 links

1. http://c-faq.com/charstring/wchar.html

2. http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.6 (C++, αλλά πρέπει να είναι ίδιο και για C λένε).

 

Θα τα κοιτάξω κάποια στιγμή (μάλλον όταν πραγματικά το χρειαστώ).

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

 

 

Ναι αυτό που λένε ισχύει αλλά είναι διαφορετικό.

 

Μπορεί κάποιος να υλοποιεί το char με όσα bit ( > 8 ) θέλει αλλά το sizeof(char) θα είναι και πάλι 1. Πχ υπάρχουν DSP που έχουν 16bit ή 32bit char και είναι ίδιο μέγεθος με τον int (οπότε και sizeof(int) είναι 1). Σημειοτέον ότι το πρότυπο ορίζει μόνο τιμές. Ενώ ο char θα είναι 16bit μπορεί πάλι να έχει μέγιστη τιμή το 127. Συνήθως αυτές οι υλοποιήσεις που char == int είναι freestanding αλλιώς θα γινόταν χαμός με τις standard συναρτήσεις.

 

 

 

Το βάζω σε spoiler για να μη φεύγουμε εκτός θέματος και χαλάμε το thread. Με λίγα λόγια το sizeof(char) δεν χρειάζεται να μπαίνει.

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

Εντός θέματος είμαστε βρε συ (ερωτήσεις για C είναι ο τίτλος).

 

Οπότε ο μόνος τρόπος να βρούμε πραγματικά σε πόσα bytes αντιστοιχεί ο char είναι με το CHAR_BIT macro;

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

Εντός θέματος είμαστε βρε συ (ερωτήσεις για C είναι ο τίτλος).

 

Οπότε ο μόνος τρόπος να βρούμε πραγματικά σε πόσα bytes αντιστοιχεί ο char είναι με το CHAR_BIT macro;

 

Ναι αλλά μόνο για αυτό χρησιμεύει (συνήθως για bit shifting και τέτοιες δουλειές). Για να βρεις τις τιμές που μπορεί να αναπαραστήσει ο τύπος πρέπει να χρησιμοποιήσεις τα _MIN, _MAX macros γιατί όπως είπαμε πριν 16bit char δεν σημαίνει απαραίτητα ότι η μέγιστη τιμή του είναι 32767 αλλά μπορεί και πάλι να έχει 127 και τα υπόλοιπα bits να είναι trap.

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

Παιδια μιας και το θέσατε εχω και εγω 2 ερωτησούλες πανω στους τύπους συγκεκριμενα σε μετατροπές :

 

 

 

 

1. Σε μια άσκηση έχω δει οτι άν έχουμε int i , long j , unsigned int k η τιμή της παράστασης

 

i+(int) j * k θα ειναι unsigned int. Γιατι ομως? Περα απο τους κανονες για τα implicit conversions ο cast (int)

δεν αναγκάζει και το κ να γινει int? ΟΠως σε μια περιπτωση της μορφης -> long i , int j =1000; i= (long) j * j

για να αποφυγουμε και το overflow πχ οπου και τα γινονται long .

 

2. Kαθως διαβαζα τους κανονες μετατροπης (C89) int -> unsigned int -> long int -> unsigned long int η αληθεια ειναι πως δεν βρηκα

καποια λογικη... στο ΓΙΑΤΙ γινονται ετσι. Ισως θα υπακουσω και εγω τυφλα στα προτυπα και δεν θα ζαλιστω αλλο... γιατι ενας εγραφε οτι έχεις μετατροπη σε ευρυτερο τυπο πραγμα που δεν ισχυει παρα μονο στην αλλαγη του unsigned int σε long int. Eμενα παντως ο παρακατω κωδικας μου δινει ισα νουμερα για int , unsigned int και long int , unsigned long int. Αρα αυτο το οτι μετατρεπεται στον "narrowest" τυπο που λεει δεν καταλαβαινω τι θελει να πει. Ειναι narrowest αυτος ο οποιος απαιτει λιγοτερα bytes για αποθηκευση. Αφου ισα bytes θελουν.

 

> 
#include<stdio.h>
int main(void)
{
int a;
unsigned int b;
long int c;
unsigned long int d;


printf("%ld , %ld , %ld , %ld " , sizeof a , sizeof b , sizeof c , sizeof d );

	return 0;
}

 

Ειναι μερικα σημεια στη C πολυ πονοκεφαλος μωρε αδερφακι μου. :/

 

Υ.Γ Στο μονο που βρισκω μια λογικη ως τωρα ειναι οταν έχουν να μετατραπουν οι floating (αν ενας εκ των 2 τελεστεων ειναι ετσι....) οπου εκει με την μια πας στον ευρυτερο τυπο + οτι αν έχεις εναν unsigned long + float ο unsigned long θα γινει float αλλιως θα στοιχιζε το κλασματικο του μερος.

 

 

 

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

Παιδια μιας και το θέσατε εχω και εγω 2 ερωτησούλες πανω στους τύπους συγκεκριμενα σε μετατροπές :

 

 

 

 

1. Σε μια άσκηση έχω δει οτι άν έχουμε int i , long j , unsigned int k η τιμή της παράστασης

 

i+(int) j * k θα ειναι unsigned int. Γιατι ομως? Περα απο τους κανονες για τα implicit conversions ο cast (int)

δεν αναγκάζει και το κ να γινει int? ΟΠως σε μια περιπτωση της μορφης -> long i , int j =1000; i= (long) j * j

για να αποφυγουμε και το overflow πχ οπου και τα γινονται long .

 

2. Kαθως διαβαζα τους κανονες μετατροπης (C89) int -> unsigned int -> long int -> unsigned long int η αληθεια ειναι πως δεν βρηκα

καποια λογικη... στο ΓΙΑΤΙ γινονται ετσι. Ισως θα υπακουσω και εγω τυφλα στα προτυπα και δεν θα ζαλιστω αλλο... γιατι ενας εγραφε οτι έχεις μετατροπη σε ευρυτερο τυπο πραγμα που δεν ισχυει παρα μονο στην αλλαγη του unsigned int σε long int. Eμενα παντως ο παρακατω κωδικας μου δινει ισα νουμερα για int , unsigned int και long int , unsigned long int. Αρα αυτο το οτι μετατρεπεται στον "narrowest" τυπο που λεει δεν καταλαβαινω τι θελει να πει. Ειναι narrowest αυτος ο οποιος απαιτει λιγοτερα bytes για αποθηκευση. Αφου ισα bytes θελουν.

 

> 
#include<stdio.h>
int main()
{
int a;
unsigned int b;
long int c;
unsigned long int d;


printf("%ld , %ld , %ld , %ld " , sizeof a , sizeof b , sizeof c , sizeof d );

	return 0;
}

 

Ειναι μερικα σημεια στη C πολυ πονοκεφαλος μωρε αδερφακι μου. :/

 

 

 

Τα implicit conversions βασίζονται στα λεγόμενα "promotion rules" και τα "conversion ranks" (https://www.securecoding.cert.org/confluence/display/seccode/INT02-C.+Understand+integer+conversion+rules) τα οποία κανείς... γήινος δεν τα θυμάται απ' έξω!

 

Για αυτό όταν δεν είμαστε σίγουροι χρησιμοποιούμε explicit casting.

 

Σε ότι αφορά τα "narrowest" types, το πρότυπο δεν αποκλείει την περίπτωση τα narrower να είναι ίσα με τα wider, διότι εγγυάται μονάχα τα κάτω όριά τους. Αποκλείει όμως κάποιο narrow type να είναι μεγαλύτερο από κάποιο wider.

 

Στο σύστημά σου, κρίνοντας από τα αποτελέσματα που παίρνεις, ο narrower int υλοποιείται με ίδιο μέγεθος με τον wider long.

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

Για αυτό... hex rules (σε συνδυασμό με typedefs, π.χ. uint8 -> unsigned char)

 

 

τιμή 1 για 8 bit στοιχείο; 0x01

τιμή 10 για 16 bit στοιχείο; 0x000A

 

Τα <inttypes.h> ήταν τρομερή προσθήκη στο C99!

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

Τα <inttypes.h> ήταν τρομερή προσθήκη στο C99!

 

 

Ναι, εάν έχεις χώρο να φορτώνεις .h files :P

 

 

Εάν είναι size critical το project (μικρή flash memory, τάξης μερικών kB), τότε τα κάνεις manually (και κόβεις από όπου μπορείς).

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

Τα implicit conversions βασίζονται στα λεγόμενα "promotion rules" και τα "conversion ranks" (https://www.securecoding.cert.org/confluence/display/seccode/INT02-C.+Understand+integer+conversion+rules) τα οποία κανείς... γήινος δεν τα θυμάται απ' έξω!

 

Για αυτό όταν δεν είμαστε σίγουροι χρησιμοποιούμε explicit casting.

 

Σε ότι αφορά τα "narrowest" types, το πρότυπο δεν αποκλείει την περίπτωση τα narrower να είναι ίσα με τα wider, διότι εγγυάται μονάχα τα κάτω όριά τους. Αποκλείει όμως κάποιο narrow type να είναι μεγαλύτερο από κάποιο wider.

 

Στο σύστημά σου, κρίνοντας από τα αποτελέσματα που παίρνεις, ο narrower int υλοποιείται με ίδιο μέγεθος με τον wider long.

 

 

Ναι βασικα αυτο συμβαινει επειδη δεν μας πειραζει αν ο int ειναι ισος σε bytes με τον unsigned

και αρα έχουν ιδιο εύρος τιμών (ιδιο εκθέτη) γιατι δεν προκαλει υπερχειλιση αυτο. Το αντιθετο που λες

θα προκαλουσε ομως. Καποιο narrow δηλαδη να ειναι μεγαλυτερο απο καποιο wider....

 

Δεν προσπαθω να τα μαθω παπαγαλια.. απλα μιας και εκανα τον κοπο και διαβασα αυτους τους κανονες

που μου ζαλισαν το κεφαλι ηθελα να καταλαβω το γιατι.

 

EDIT: Άκυρο στους unsigned δεν υπάρχει υπερχειλιση λογω modulo 2^n :P

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

Ναι, εάν έχεις χώρο να φορτώνεις .h files :P

 

 

Εάν είναι size critical το project (μικρή flash memory, τάξης μερικών kB), τότε τα κάνεις manually (και κόβεις από όπου μπορείς).

 

Σε αυτές τις περιπτώσεις δεν τα χρειάζεσαι καθόλου ρε συ, μιας και μιλάμε για platform specific coding. Οπότε όταν ξέρεις πως στην πλατφόρμα σου είναι π.χ. ο char 1 byte, ο short 2 και ο int 4, κλπ, δεν υπάρχει λόγος να χρησιμοποιήσεις καθόλου το <inttypes.h>

 

ΥΓ. Εκτός αν δεν κατάλαβα σωστά... τι εννοείς "manually" ?

 

Ναι βασικα αυτο συμβαινει επειδη δεν μας πειραζει αν ο int ειναι ισος σε bytes με τον unsigned

και αρα έχουν ιδιο εύρος τιμών στον εκθέτη γιατι δεν προκαλει υπερχειλιση αυτο. Το αντιθετο που λες

θα προκαλουσε ομως. Καποιο narrow δηλαδη να ειναι μεγαλυτερο απο καποιο wider....

...

Οι signed και οι unsigned είναι πάντα ίσοι σε bytes (ίδιο width δηλαδή), σε οποιονδήποτε τύπο. Μόνο στο arithmetic conversion διαφέρουν, όπου παίρνει προτεραιότητα ο unsigned (αν θυμάμαι σωστά δηλαδή).

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

 

Οι signed και οι unsigned είναι πάντα ίσοι σε bytes (ίδιο width δηλαδή), σε οποιονδήποτε τύπο. Μόνο στο arithmetic conversion διαφέρουν, όπου παίρνει προτεραιότητα ο unsigned (αν θυμάμαι σωστά δηλαδή).

 

Ok.

 

Αρα δεν έχει σημασια αν και αυτο εδω (παρολο που εχει casting που το αναγκαζει σε int) τελικα παράξει unsigned int oλο η τιμη της εκφρασης

 

>

i + (int) j * k ; 

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

Ok.

 

Αρα δεν έχει σημασια αν και αυτο εδω (παρολο που εχει casting που το αναγκαζει σε int) τελικα παράξει unsigned int oλο η τιμη της εκφρασης

 

>

i + (int) j * k ; 

 

Αυτό είναι εξαιρετικά σπάνιο να υπάρξει μέσα σε κώδικα, τουλάχιστον όχι χωρίς κάποιο σχόλιο που να εξηγεί τι κάνει και γιατί. Τέτοιοι κώδικες γενικώς είναι παραδείγματα προς αποφυγή.

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

Επισκέπτης
Αυτό το θέμα είναι πλέον κλειστό για περαιτέρω απαντήσεις.

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