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

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

Δημοσ.

Θα με τρελάνει ο mingw gcc (και ο σκέτος 4.6.2, και του cygwin 4.5.3)

 

Είναι φυσιολογικό ο παρακάτω κώδικας να δίνει πάντα 0 στα "%Lg" με οποιοδήποτε pos και οποιοδήποτε s, ακόμα και στα αντίθετα endians; Υποτίθεται πως το έχουν λύσει το θέμα με την stdio βιβλιοθήκη (π.χ. http://mingw-users.1...-td1650580.html) ... αλλά δεν το βλέπω. Του cygwin μάλιστα ενίοτε κρασάρει στο "%La".

 

Θα μπορούσε κάποιος να δοκιμάσει σε κανονικό gcc (unix/linux/mac) ;

 

 

 

>
/*** C99 ***/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>

/* ------------------------------------------------- */
void endian_toggle( uint8_t *data, int nbytes )
{
register int i = 0;
register int j = nbytes-1;

/* reverse bytes */
for (; i < j; i++,j--) {
	uint8_t byte = data[i];
	data[i] = data[j];
	data[j] = byte;
}

return;
}
/* ------------------------------------------------- */
void pretty_hexdump( const char *label, const uint8_t *buf, size_t bufsize )
{
if ( !label || !buf )
	return;

if ( label )
	printf( "%s", label );

for (size_t i=0; i < bufsize; i++) {
	if ( i != 0 && i % 16 == 0 )
		puts("\b");
	printf( "%02"PRIx8" ", buf[i] );
}
puts("\b");

return;
}
/* ------------------------------------------------- */
int main( void )
{
char s[100+1] = "hfewrweior eior uewiu weiuew ew weweo eueueuero 779794354395fjkfhi";
int  pos = 5;
long double ld;;
const size_t ldsize = sizeof( long double );

pretty_hexdump( "s hexdump:\n", (uint8_t *)s, sizeof(s) );

memcpy( &ld, &s[pos], ldsize );
pretty_hexdump( "\nld hexdump (cur.endian): ", (uint8_t *)&ld, ldsize );
printf( "ldouble val: %Lg / %La\n", ld, ld );

endian_toggle( (uint8_t *)&ld, ldsize );
pretty_hexdump( "\nld hexdump (opp.endian): ", (uint8_t *)&ld, ldsize );
printf( "ldouble val: %Lg / %La\n", ld, ld );

system("pause");	/* windows only */
return 0;
}

 

 

ΥΓ. Σε Pelles-C δουλεύει, αλλά αυτή διαχειρίζεται όμοια τα double και τα long-double (8 bytes) ενώ ο gcc έχει 12 bytes για τα long-doubles (αλλά αν δεν δουλεύουν τι να τα κάνεις :lol:)... σε vs-studio δεν ξέρω αν γίνεται καν compile o κώδικας (C99), ας το δοκιμάσει κι εκεί κάποιος αν δεν βαριέται (νομίζω όμως πως όντως η βιβλιοθήκη των Windows κάνει πάντα treat ίδια τα doubles και των long-doubles).

Δημοσ.

Το string που έχεις γράψει είσαι σίγουρος ότι δημιουργεί "τιμές" που μπορούν να αναπαρασταθούν ?

 

Linux 64bit (16byte long double)

>
ld hexdump (cur.endian): 77 65 69 6f 72 20 65 69 6f 72 20 75 65 77 69 75
ldouble val: 6.53001e+3886 / 0x6.96520726f696577p+12909

ld hexdump (opp.endian): 75 69 77 65 75 20 72 6f 69 65 20 72 6f 69 65 77
ldouble val: 1.60381e+2883 / 0x6.f72207565776975p+9575

 

Linux 32bit (12byte long double)

>
ld hexdump (cur.endian): 77 65 69 6f 72 20 65 69 6f 72 20 75
ldouble val: 6.53001e+3886 / 0x6.96520726f696577p+12909

ld hexdump (opp.endian): 75 20 72 6f 69 65 20 72 6f 69 65 77
ldouble val: 1.8896e+3193 / 0x7.22065696f722075p+10605

 

Solaris 32bit

>
ld hexdump (cur.endian): 77 65 69 6f 72 20 65 69 6f 72 20 75
ldouble val: NaN / 0x1.d2ca40e4ded2caeep+12912

ld hexdump (opp.endian): 75 20 72 6f 69 65 20 72 6f 69 65 77
ldouble val: NaN / 0x1.e440cad2dee440eap+10608

Δημοσ.

Ω, ταχύτατος, ευχαριστώ πολύ!!

 

Μόλις κατάφερα να το δοκιμάσω κι εγώ σε FreeBSD (remotely) και είναι κι εκεί ΟΚ! Όπως και στα συστήματα που το δοκίμασες! Ο *&%^%&mingw-gcc φταίει τελικά!

 

Για το string, είναι τελείως τυχαίο! Είναι για έναν HexViewer κονσόλας που φτιάχνω στον ελεύθερο χρόνο μου. Δίνω παρακάτω 2 εικόνες, η 1η είναι compiled με Pelles C 64bit, και η 2η με mingw-gcc (αυτός δείχνει πάντα 0 το "Lg")...

 

post-38307-0-12486100-1332864371_thumb.jpg post-38307-0-22300000-1332864397_thumb.jpg

 

Και πάλι ευχαριστώ!

Δημοσ.

Και εγώ τα ίδια αποτελέσματα με τον imitheos είχα σε 32bit linux

με gcc 4.4.3

 

Το δοκίμασα από περιέργεια και στα windows (mingw) και :) βγάζει 0 στο %Lg.

 

Αστείο!

Δημοσ.

Ευχαριστώ!

 

Σε Windows μόνο o mingw-gcc πρέπει να έχει πρόβλημα, γιατί διαχειρίζεται τους long-double ως 96-μπιτους, ενώ η stdio βιβλιοθήκη των Windows που χρησιμοποιούν σχεδόν όλοι οι Windows compilers τους κάνει treat ως 64-μπιτους (όμοια με τους double δηλαδή).

Δημοσ.

Μόλις κατάφερα να το δοκιμάσω κι εγώ σε FreeBSD (remotely) και είναι κι εκεί ΟΚ! Όπως και στα συστήματα που το δοκίμασες! Ο *&%^%&mingw-gcc φταίει τελικά!

 

Και πάλι ευχαριστώ!

 

Είναι σίγουρα οκ όμως ? Το Solaris δίνει Not a Number όπως βλέπεις. Δες τα bytes μια κανονικής τιμής (πχ 5.2) και βάλε αυτά στο string για να είσαι σίγουρος τι παίζει.

Δημοσ.

Είναι σίγουρα οκ όμως ? Το Solaris δίνει Not a Number όπως βλέπεις. Δες τα bytes μια κανονικής τιμής (πχ 5.2) και βάλε αυτά στο string για να είσαι σίγουρος τι παίζει.

Ναι, το είχα κάνει ήδη... άλλοτε δείχνει κι άλλοτε όχι, υποθέτω τα παίζει όταν ξεπεραστούν τα 64 bits, αλλά δεν ξέρω πως αποθηκεύει τους long- double ο mingw-gcc για να παίξω με το όριο.

 

Έχω συγκρίνει όμως τους float και double με άλλους hex-editors και συμφωνούμε, οπότε εφόσον η διαδικασία που ακολουθώ για τους long-double είναι η ίδια, θα είναι σωστό κι αυτό! Βέβαια από compiler σε compiler θα δίνει άλλο αποτέλεσμα, αλλά αυτό είναι αναμενόμενο.

EDIT:

 

...

Linux 64bit (16byte long double)

>
ld hexdump (cur.endian): 77 65 69 6f 72 20 65 69 6f 72 20 75 65 77 69 75
ldouble val: 6.53001e+3886 / 0x6.96520726f696577p+12909

...

Πω πω... υπάρχουν και 16-bytes long-double? Φτου... δεν θα χωράνε στην 1η γραμμή :(

(μάλλον θα αφαιρέσω το ascii από εκεί... πολύ ντράβαλο η περιορισμένη χωρητικότητα της κονσόλας).

Δημοσ.

Ναι, το είχα κάνει ήδη... άλλοτε δείχνει κι άλλοτε όχι, υποθέτω τα παίζει όταν ξεπεραστούν τα 64 bits, αλλά δεν ξέρω πως αποθηκεύει τους long- double ο mingw-gcc για να παίξω με το όριο.

 

Solaris 32bit

>
s hexdump:
00 68 66 66 66 66 66 a6 01 40 00 00 75 65 77 69 

ld hexdump (cur.endian): 00 68 66 66 66 66 66 a6 01 40 00 00 
ldouble val: 5.2 / 0x1.4cccccccccccd000p+2

 

Χρησιμοποιώντας στο s τις τιμές που φαίνονται παραπάνω, παίρνω όπως βλέπεις κανονικά 5.2 αντί για NaN οπότε ίσως να φταίνε οι τιμές που δεν παίζει ο mingw (ίσως και όχι :) )

Δημοσ.

Αυτό είχα κάνει κι εγώ. Βασικά είχα βάλει το pretty_hexdump να δείχνει 10δική βάση (PRId8) έκανα ανάθεση στον ld π.χ. το 456.8976, είδα από το pretty_ dec(hex)dump ποιες τιμές αντιστοιχούν, κι έκανα με αυτές initialize το s.

 

Όμως, όπως έγραψα και παραπάνω, δεν ξέρω πως απεικονίζει τις τιμές στα long-double ώστε να βάλω μια τιμή πάνω από τα 64-bits (π.χ. ποιος αριθμός κινητής υποδιαστολής είναι το όριο των 64-bits ; )

Δημοσ.

Όμως, όπως έγραψα και παραπάνω, δεν ξέρω πως απεικονίζει τις τιμές στα long-double ώστε να βάλω μια τιμή πάνω από τα 64-bits (π.χ. ποιος αριθμός κινητής υποδιαστολής είναι το όριο των 64-bits ; )

 

Μάλλον δεν κατάλαβα καλά αλλά _αν_ κατάλαβα γιατί δεν βάζεις μια τιμή και να δεις πως την απεικονίζει ? Έτσι δεν θα χρειάζεται να ψάξεις την απεικόνιση. πχ

 

>
memcpy( &ld, &s[pos], ldsize );
[b]	ld = 9.7;[/b]
pretty_hexdump( "\nld hexdump (cur.endian): ", (uint8_t *)&ld, ldsize );
printf( "ldouble val: %Lg / %La\n", ld, ld );

 

Έτσι θα σου εμφανίσει την απεικόνιση του 9.7 και μετά μπορείς να το βάλεις στο s.

Δημοσ.

Μάλλον δεν κατάλαβα καλά αλλά _αν_ κατάλαβα γιατί δεν βάζεις μια τιμή και να δεις πως την απεικονίζει ? Έτσι δεν θα χρειάζεται να ψάξεις την απεικόνιση. πχ

 

 

 

Έτσι θα σου εμφανίσει την απεικόνιση του 9.7 και μπορείς να το βάλεις στο s.

Αυτό ακριβώς σου περιέγραψα βρε στο αμέσως προηγούμενο post :)

 

ΥΓ. Το βασικό ζητούμενο (για να βγάλουμε συμπέρασμα της προκοπής) είναι να βρούμε τον μέγιστο αριθμό κινητής υποδιαστολής που απεικονίζεται σε 64-bits (δεν έχω ιδέα πως θα το βρούμε αυτό, νομίζω είναι implementation defined? δεν θυμάμαι καθόλου) και κατόπιν να τεστάρουμε τον mingw-gcc με μια τιμή μεγαλύτερη από αυτήν ;)

 

EDIT:

 

Ούτε καν πως απεικονίζονται οι αρνητικοί κινητής-υποδιαστολής δεν θυμάμαι... δεν ξέρω δηλαδή ποιο pattern ακολουθούν ώστε π.χ. να ανάψω όλα τα σχετικά bits για τον μέγιστο 64μπιτο θετικό και να το κάνω μετά "%Lg".για να δω τι θα βγάλει.

 

EDIT 2:

 

Τα 'χω παίξει (σημάδι να σταματήσω)...

 

>#include <float.h>
...
DBL_MAX
...
LDBL_MAX

Τσεκάρισα και τυπώνει κανονικά οτιδήποτε είναι in-range, ενώ για τα υπόλοιπα βγάζει "inf" (αν και είμαι σε άλλο μηχάνημα τώρα: XP 32bits, πριν ήμουν σε 7 64bits)

 

Οπότε υποθέτω υπάρχουν κάποια byte-patterns τα οποία δεν συνάδουν με το long-double φορμά και βγάζει 0; Κάτι τέτοιο πρέπει να παίζει.

 

Τα παρατάω για σήμερα, πάω σπίτι.

Δημοσ.

ΥΓ. Το βασικό ζητούμενο (για να βγάλουμε συμπέρασμα της προκοπής) είναι να βρούμε τον μέγιστο αριθμό κινητής υποδιαστολής που απεικονίζεται σε 64-bits (δεν έχω ιδέα πως θα το βρούμε αυτό, νομίζω είναι implementation defined? δεν θυμάμαι καθόλου) και κατόπιν να τεστάρουμε τον mingw-gcc με μια τιμή μεγαλύτερη από αυτήν ;)

 

 

Συνήθως ακολουθείται το IEEE754. Ο μεγαλύτερος 64bitος θετικός είναι 0x7FEFFFFFFFFFFFFF αλλά λόγω της απεικόνισης δεν μπορείς να βάλεις μια τιμή μεγαλύτερη για να δοκιμάσεις την περίπτωση των 12bytes.

 

Τσεκάρισα και τυπώνει κανονικά οτιδήποτε είναι in-range, ενώ για τα υπόλοιπα βγάζει "inf" (αν και είμαι σε άλλο μηχάνημα τώρα: XP 32bits, πριν ήμουν σε 7 64bits)

 

Οπότε υποθέτω υπάρχουν κάποια byte-patterns τα οποία δεν συνάδουν με το long-double φορμά και βγάζει 0; Κάτι τέτοιο πρέπει να παίζει.

 

Καλά υπέθεσα ότι έφταιγαν οι τιμές λοιπόν. Ότι υπάρχουν trap τιμές (είτε δεν είναι αριθμοί, είτε δηλώνουν το άπειρο, κτλ) φυσικά υπάρχουν. Τώρα γιατί αυτές οι τιμές έπαιζαν σε linux δεν ξέρω. Ίσως η glibc κάνει κάποιο rounding και εμφανίζει την επόμενη δυνατή τιμή (πολύ πιθανό φυσικά να λέω χαζομάρες).

Δημοσ.

Κάτι τέτοιο πρέπει να παίζει, ναι. Βασικά δεν σκοπεύω να ασχοληθώ άλλο, μιας και βγάλαμε τελικά άκρη με το <float.h> (που το είχα ξεχάσει τελείως χτες).

 

Άσχετο, υπάρχει σοβαρή Ελληνική μετάφραση των "big & little endian"... ισχύει ένα "μεγακρικός" που βρήκα (τι σόι λέξη είναι αυτή :lol:) ... αν ναι, πως είναι το "little";

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

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

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

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

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

Σύνδεση

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

Συνδεθείτε τώρα
  • Δημιουργία νέου...