Il y a longtemps de cela, sur un code que je proposais sur ce site, on m'a fait une remarque sur un fwrite :
"Fais gaffe quand-même parce qu'un INT ne fera pas forcément 4 octets sur toutes les bécanes."
Je me souvient très bien avoir fait une recherche dans la foulée, et effectivement, il apparait que le INT est le plus souvent composé d'un nombre d'octets "naturel" pour l'UC, donc c'est selon, Ok, d'accord. Et encore, je pense que l'OS vient jouer les trouble-fête parce que sur un i5 (64 bits "naturel", donc) et un xp pro 32, mon int fait quand même que 4 octets...
Bref, sur ce, je continue ma petite vie en restant convaincu qu'un char est sur un octet, qu'un short sur 2, un long 4 et un long long 8. Ce sont donc les types que j'utilise lorsque j'ai besoin d'être certain d’accéder à X octets, dans un fichier par exemple.
Et là, (tardivement, peut-être) je me rend compte qu'en fait ils ne feraient pas X Octets mais AU MOINS, donc un char AU MOINS 1 octet, un short AU MOINS 2 octets etc, donc seule la taille minimale serait garantie...
Donc, les vrais seuls types auxquels on peux faire confiance au final, ce seraient les uint8_t, sint8_t, etc, en passant par 16,32 et 64 ?
Surtout qu'ici, page 34, ils définissent INT_MAX à 32767 et UINT_MAX à 65535... ça sent le 16 bits un peu quand-même... ils sont pas un peu à la ramasse ?
Du coup, en fait, en vrai, c'est le bordel total et on ne peut se fier à rien ? Chacun fait ce qu'il veut dans coin ? Si dans dix ans un type décide que le char fait désormais 2 octets, tous ceux qui scannent leurs fichiers au *char au lieu d'un *uint8_t vont se retrouver marron ?
Quelqu'un saurait-il m'apporter quelques précisions là dessus ? Ok, il y a la norme, mais je ne pige pas tout quand-même...
Et là, (tardivement, peut-être) je me rend compte qu'en fait ils ne feraient pas X Octets mais AU MOINS, donc un char AU MOINS 1 octet, un short AU MOINS 2 octets etc, donc seule la taille minimale serait garantie...
Donc, les vrais seuls types auxquels on peux faire confiance au final, ce seraient les uint8_t, sint8_t, etc, en passant par 16,32 et 64 ?
Surtout qu'ici, page 34, ils définissent INT_MAX à 32767 et UINT_MAX à 65535... ça sent le 16 bits un peu quand-même... ils sont pas un peu à la ramasse ?
Je pense que la raison pour laquelle il est écrit que INT_MAX = 32767 c'est justement parce que, comme tu l'as dis, ils font AU MOINS... par exemple sur un processeur 16 bits, sizeof(int) = 2.
drx a écrit:
Du coup, en fait, en vrai, c'est le bordel total et on ne peut se fier à rien ? Chacun fait ce qu'il veut dans coin ? Si dans dix ans un type décide que le char fait désormais 2 octets, tous ceux qui scannent leurs fichiers au *char au lieu d'un *uint8_t vont se retrouver marron ?
Si tu fais des programmes pour PC, tu n'as pas à t'en soucier... ton programme ne se lancera même pas sur un processeur 16 bits. Si tu programmes des micro-contrôleurs en revanche, je pense en effet qu'il faudra que tu t'adaptes...
Et passer le char de 1 à 2 octets, je ne pense pas que ça se fasse comme ça du jour au lendemain, juste parce que "un type décide que le char fait désormais 2 octets" . Ne t'en fais pas !
Dans ton programme, et plus particulièrement dans ta partie traitement, à moins que tu saches que c'est destiné a du matériel particulier, il faut simplement que tu t'arranges pour que ça tienne dans les types généraux. Donc tu t'assures que tu ne vas pas au-delà du "au moins" et tout va bien.
Pour ce qui est de la lecture dans les fichiers/réseau/whatever, tu utilises les types (u|s)(type)_(size)t qui sont fixés et ne peuvent pas changer d'une archi à l'autre. Par ailleurs, pour ce genre de cas, il faut aussi gérer toutes les jolies histoires d'indianisme (sur les bits, sur les octets), etc ... et donc de toute façon, tu as déjà tout plein de problèmes en plus de la taille des types.
EDIT : Ah, et à moins que tu sois certain que dans tes architectures cibles il y ait du 16 bits, ne te casse pas le cul avec leur support, plus vite elles seront remisées, mieux le monde se portera.
- Edité par Ksass`Peuk 16 septembre 2013 à 13:53:31
Bref, sur ce, je continue ma petite vie en restant convaincu qu'un char est sur un octet, qu'un short sur 2, un long 4 et un long long 8. Ce sont donc les types que j'utilise lorsque j'ai besoin d'être certain d’accéder à X octets, dans un fichier par exemple.
Du coup, en fait, en vrai, c'est le bordel total et on ne peut se fier à rien ? Chacun fait ce qu'il veut dans coin ? Si dans dix ans un type décide que le char fait désormais 2 octets, tous ceux qui scannent leurs fichiers au *char au lieu d'un *uint8_t vont se retrouver marron ?
Attention, un long c'est 8 octets sur un système PC contemporain. 4 octets, c'était le cas sur les systèmes 32 bits. Ca reste encore bien utilisé, mais il faut avoir conscience que c'est dépassé. Encore plus dépassé, Windows 3 avait des int de 2 octets.
Chacun fait presque ce qu'il veut dans son coin. L'idée de la norme, c'est que le C puisse être porté sur un système avec des bytes de 9 bits et des mots de 36 bits, tout en respectant la norme.
Il peut aussi exister des processeurs spécialisés qui n'ont qu'une seule taille de donnée: 32 bits. Dessus, un char fait 32 bits. Et voilà. De toute façon de tels systèmes ne sont pas destinés à recevoir des programmes généralistes, donc on s'en soucie peu, et on code pour des systèmes avec des char de 8 bits avec représentation signée en complément à deux.
Entre l'endianess, les char signés ou pas, la taille des int, des long et des pointeurs, il y a déjà de quoi donner à réfléchir pour la portabilité.
- Edité par Marc Mongenet 16 septembre 2013 à 16:19:29
Effectivement, dans un sens, je ne cherche pas non-plus à voir mes programmes tourner sur des 68000, mais sans aller chercher aussi loin, et comme le remarquent Marc Mongenet et Fvirtman, il n'y a pas besoin d'aller bien loin pour avoir des soucis. Si le long fait 8 Octets sous Linux, alors mes accès de fichiers vont fatalement foirer sur cette plateforme.
Je ne suis pas un ardent défenseur du "tout portable", parce que je mes programmes restent destinés à du matos contemporain (et futur autant que possible), mais il y a minimum quand-même, et d'autres OS que Win32/64 en font partie.
Je vais donc m'empresser de faire un tour dans ma lib pour corriger tout ça.
Cependant, en continuant mes recherches, je n'arrive pas à trouver de liste exhaustive des type "garantis", je suppose que les (s|u)int(taille)_t en font partie, mais qu'en est-il des autres comme size_t par exemple ?
Parce que j'ai tendance à pas mal utiliser ce type, outre sa taille, c'est le genre de type qui sert également de commentaire dans la mesure où je l'utilise fréquemment pour stocker les volumes.
J'en conclu également que sur un changement de plateforme, il convient de re-compiler non-seulement le programme, mais également les utilitaires pour reformater les fichiers utiles à l'application... Du coup le transfert de fichiers d'une plateforme à l'autre devient improbable...
Et enfin, une dernière question :
Y a-t-il un moyen de conditionner le type d'une variable à sa déclaration ? J'imagine que oui avec des directives preproc, et donc pas en "dynamique". L'idée serait d'avoir un truc du genre :
Cependant, en continuant mes recherches, je n'arrive pas à trouver de liste exhaustive des type "garantis", je suppose que les (s|u)int(taille)_t en font partie, mais qu'en est-il des autres comme size_t par exemple ?
size_t n'a pas une taille garantie. Ce type est typiquement fait pour passer tes allocations, or la taille maximale d'allocation n'est pas la même en fonction de ton architecture (et donc de la taille de tes pointeurs ).
drx a écrit:
J'en conclu également que sur un changement de plateforme, il convient de re-compiler non-seulement le programme, mais également les utilitaires pour reformater les fichiers utiles à l'application... Du coup le transfert de fichiers d'une plateforme à l'autre devient improbable...
Ben, oui il faut recompiler, mais tes fichiers eux doivent avoir le même format (taille de type compris) sur toutes les machines. C'est là l'intérêt de passer par les types fixés sus-nommés.
drx a écrit:
Y a-t-il un moyen de conditionner le type d'une variable à sa déclaration ? J'imagine que oui avec des directives preproc, et donc pas en "dynamique". L'idée serait d'avoir un truc du genre :
L'avenir de la portabilité va être sombre à cause des architectures 64 bits LP64 et LLP64, qui vont poser pas mal de soucis, quand tout le monde compilera en 64....
Effectivement, dans un sens, je ne cherche pas non-plus à voir mes programmes tourner sur des 68000, mais sans aller chercher aussi loin
mais qu'en est-il des autres comme size_t par exemple ?
Oh, un 680x0 n'a rien de bien exotique. C'est d'ailleurs le processeur qui a servi de base à beaucoup de stations de travail (notamment Unix). Et aussi à GCC (http://gcc.gnu.org/wiki/History).
Sinon, pour size_t, il est garanti qu'il est entier non signé. Il permet de représenter la taille de tout objet; c'est le type résultant d'un sizeof.
Cependant, en continuant mes recherches, je n'arrive pas à trouver de liste exhaustive des type "garantis", je suppose que les (s|u)int(taille)_t en font partie, mais qu'en est-il des autres comme size_t par exemple ?
En fait, la norme ne te garantit pas l'existence des types de taille fixe. C11 (N1570), § 7.20.1.1, Exact-width integer types, al. 3, p. 290.
These types are optional.
Elle ne te garantit que la présence des types u?intleastXX_t, u?intfastXX_t et u?intmax_t. Ksass`Peuk a écrit:
>> drx a écrit:
>> Y a-t-il un moyen de conditionner le type d'une variable à sa déclaration ? J'imagine que oui avec des directives preproc, et donc pas en "dynamique".
Oui :
#ifdef sizeof(int) == 1
typedef uint8t m_int;
ifdef sizeof(int) == 2
typedef uint16t m_int;
//[...]
endif
</pre>
Je suppose que tu voulais utiliser la directive #if et non #ifdef ? Sinon, de telles expressions de contrôle ne sont pas possible au niveau du préprocesseur car les mots-clés sont remplacés par 0 au sein de celles-ci. C11 (N1570), § 6.10.1, Conditional inclusion, al. 4, p. 163.
Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text. If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers (including those lexically identical to keywords) are replaced with the pp-number 0, and then each preprocessing token is converted into a token [...].
Soit dit en passant, cela peut donner des trucs assez amusants, comme ceci par exemple :
#if if == else
#error Ben quoi ?
#endif
int
main(void)
{
return 0;
}
drx a écrit:
J'en conclu également que sur un changement de plateforme, il convient de re-compiler non-seulement le programme, mais également les utilitaires pour reformater les fichiers utiles à l'application... Du coup le transfert de fichiers d'une plateforme à l'autre devient improbable...
Si c'est le cas, il y a un soucis dans ta mise en œuvre des utilitaires gérant les fichiers. Techniquement, tu n'as qu'une seule chose à fixer : le format de ton fichier et la représentation de ses données (taille, boutisme, etc). Pour le reste, il te suffit de récupérer les données à l'aide de tableaux de char.
Si c'est le cas, il y a un soucis dans ta mise en œuvre des utilitaires gérant les fichiers. Techniquement, tu n'as qu'une seule chose à fixer : le format de ton fichier et la représentation de ses données (taille, boutisme, etc). Pour le reste, il te suffit de récupérer les données à l'aide de tableaux de char.
Et oui, justement. Par exemple dans l'utilitaire qui regroupe mes fichier de ressources, ma table d'index est une table de long, justement parce que je croyais, comme précisé dans mon premier post qu'un long serait de taille constante quelque soit le système. Table que je récupère donc sous forme de table de long dans l'appli qui a besoin des ressources, sauf que si je compile mon appli chez Marc qui a un long de 8, au moment d'aller chercher la table dans le fichier ça va lamentablement foirer.
Donc, faire une relecture avec l'opérateur sizeof : fread(*maVariable,sizeof(long),1,fichier) est clairement une erreur, il est plus sécurisé de fixer en dur les volumes en fonction de la taille des types du système qui a créé le fichier : fread(*maVariable,4,1,fichier).
Ensuite dans le cas de stockage/relecture d'une structure, il faudrait le faire membre par membre ?
Exemple, en mettant de côté les problèmes de padding et d'indianness si vous voulez bien, en admettant que Marc déclare chez lui une structure du genre :
struct demo
{
long varA;
int varB;
}
Donc 8+4 Octets chez Marc, (si je ne me trompe) puis qu'il colle dans un fichier au fwrite(*demo,sizeof(demo),1,fichier) pour me l'envoyer. Avec la même structure de (4+4) Octets si le "lecteur" est compilé chez moi, j'aurai beau relire membre par membre en sachant que je dois lire (8+4) Octets, je vais quand-même être dans le caca pour stocker le contenu de la structure en mémoire non ? La structure déclarée dans le "lecteur" du fichier ne peut décidément pas être la même selon le système puisqu'il va me falloir un long long et un int pour arriver aux 12 octets nécessaires...
Et mettons, que j'aille les chercher au tableau de char, sachant pertinemment que la première valeur à aller chercher est sur 8 octets, je vais la coller dans un unsigned char[8], et ensuite ? Si je veux extraire la valeur, le problème reste le même, il faut un long*ptr chez Marc et un long long*ptr chez moi...
En fait, il arrive un moment où le type en soi importe peu, mais où c'est la taille qui compte (contrairement à ce qui se dit ) et que savoir que ma structure est sur 12 Octets dont un entier sur 8 et un sur 4, est la seule chose dont j'ai besoin, que ce soient des ints, des doubles, des choux ou des carottes...
Je comprend bien que le principe de portabilité ne s'applique qu'au code et non à l'exécutable, je ne m'attend pas à ce qu'un truc compilé pour Xbox tourner sur une PS et vice-versa. Mais entre 2 PC, même avec des OS différents alors que l'architecture physique va être la même (ou très proche), c'est un peu abusé si on ne peut pas être certain de la taille d'un type et refiler un fichier d'un système à l'autre.
Toujours est-il que je vous remercie bien pour vos remarques, ça m'a permit d'apprendre des trucs et de me rendre compte que les choses ne sont pas toujours aussi simples qu'elles semblent, parce qu'en quelque sorte, il s'agît d'un "faux vrai problème", puisque ma méthode a toujours fonctionné jusqu'ici (sous Win32/64 au moins). Donc jusqu'au jours où j'aurai tenté de compiler chez Marc (j'apporterai les bières ) je n'ai aucun moyen de savoir que ça ne va plus fonctionner...
@Taurre : j'aurais bien cité mais ça ne fonctionne plus ... Donc oui c'est bien "#if" que je voulais mettre, comme quoi il faut pas faire de copier/coller (et surtout pas hâtifs) .
Il est normal qu'il existe beaucoup de diversité sur les PC. Ce sont des machines avec un historique inégalé, qui ont un mode de fonctionnement 16 bits, un 32 bits, un 64 bits...
Concernant la sérialisation (sauvegarde sur fichier, transfert réseau), elle doit être spécifiée octet par octet, sinon elle n'est pas portable.
En effet, souvent, dans les fichiers binaires, les normes (quand ils sont documentés - mais même quand ils ne le sont pas en fait) parlent de int32, de int16, ou autres types dont les tailles sont fixées. Jamais de "int".
Il existe aussi une documentation sur l'endianness dans le fichier. Soit elle est fixée (et c'est au lecteur de s'adapter), soit il y a un char8, voir un seul bit au début, qui définit l'endianness dans le fichier.
Ensuite dans le cas de stockage/relecture d'une structure, il faudrait le faire membre par membre ?
En effet, il est nécessaire de convertir chaque membre en un tableau de char et d'écrire ensuite ce tableau dans le fichier (et inversément pour la lecture). Cela peut se faire facilement à l'aide de quelques fonctions dédiées.
Tu te fais des fonctions "LireFloat", "LireDouble", "LireInt32" ; "EcrireFloat" ....
Ce sont elles qui s'occupent de gérer l'endianness voulu. Et hop, une fois ces fonctions bas niveau implémentées, fini les soucis d'endianness.
Ensuite, tu peux te faire des fonction "EcrireTableauFloat" ... Ou "EcrireCetteStructure".... Et les fonctions symétriques "LireTableauFloat"....
Bref, se faire des couches pour faire très vite abstraction des soucis bas niveau.
Chaque couche a ses soucis, ses particularités, ses précautions. A nous de bien faire pour que ces choses restent dans leur couche, et ne remontent pas plus haut. Sinon, en haut, on se noie.
Désolé d'insister mais, soit je me suis mal fait comprendre, soit vous lisez en diagonal.
Quelque soit la méthode utilisée pour créer le fichier, si la bécane d'en face n'a pas des types de même taille, même en recompilant le lecteur (et surtout en recompilant, j'ai envie de dire), il lui sera impossible d'interpréter correctement les données du ficher sans revoir le code ou reformater le fichier pour cette plateforme.
si par exemple, mon code est celui-ci, un exemple comme un autre hein :
Avec un double de 8 chez lui et un de 4 chez moi, la relecture reste impossible sans recréer le fichier chez moi. Sauf si son programme tourne chez moi sans avoir à recompiler puisque les constantes resterons les même (sizeof())...
Maintenant, je me suis essayé à un code (pas testé, j'espère avoir pensé à tout) en suivant vos conseilles, Uchar par Uchar:
int writeValueInFile(void*val, size_t size, FILE* file)
{
/***Declarations***/
int ret=0;
/***PRL***/
if (val==NULL || size==0 || file==NULL)
return FUNC_ERR;
/**Execution**/
switch (size)
{
case 1:
ret=writeOctInFile(val, file);
break;
case 2:
ret=writeWordInFile(val,file);
break;
case 4:
ret=writeDWordInFile(val,file);
break;
case 8:
ret=writeQWordInFile(val,file);
break;
default:
fprintf(stderr,"Valeur exotique ou d'une autre planète, va t'acheter un pc...\n);
ret=FUNC_ERR;
break;
}
return ret;
}
/**Exemple en 32 bits...*/
int writeDWordInFile(void* val,FILE*file)
{/*32 bits vers le fichier en lilendian*/
/***Déclarations***/
usigned char *ptr=val, recover=0;
int index,ret=FUNC_OK;
(void)(*backOp[2])(unsigned char*, int)={swapEndLilToBig,swapEndLilToMed};
/***PRL***/
if(val==NULL || file==NULL)
return FUNC_ERR;
/***Executions***/
if(BYTE_ORDER==BIG_ENDIAN)
{/*convertir en lil Endian*/
swapEndBigToLil(ptr,4);
recover=1;
}
else if(BYTE_ORDER==MID_ENDIAN)
{/*convertir en lil Endian*/
swapEndMedToLil(ptr,4);
recover=2;
}
if (fwrite(ptr,1,4,file)<4)/*écrire dans le fichier*/
ret=FUNC_ERR;
if (recover)/*rétablir l'état de la valeur*/
backOp[recover-1](ptr,4);
return ret;
}
Donc là, normalement, je suis plutôt bien blindé pour l'écriture (même si pas forcément optimisé et si ça fait cher pour coller 4 octets dans un fichier ), mais reste quand même que si je créé un fichier ainsi pour le filer à Marc ou Fvirtman, ils seront de toute façons également incapables de lire le fichier puisque le retour de readValueInFile(sizeOf(long),fichier), dans le même principe que les fonctions ci dessus en version "lecture" va lire une valeur sur 8 et non sur 4 octets.
Donc, pas le choix, changement de plateforme, c'est forcément reformatage des fichiers pour cette plateforme...
Taurre a écrit:
Salut,
[...]
drx a écrit:
J'en conclu également que sur un changement de plateforme, il convient de re-compiler non-seulement le programme, mais également les utilitaires pour reformater les fichiers utiles à l'application... Du coup le transfert de fichiers d'une plateforme à l'autre devient improbable...
Si c'est le cas, il y a un soucis dans ta mise en œuvre des utilitaires gérant les fichiers. Techniquement, tu n'as qu'une seule chose à fixer : le format de ton fichier et la représentation de ses données (taille, boutisme, etc). Pour le reste, il te suffit de récupérer les données à l'aide de tableaux de char.
Ai-je été plus clair sur ma démonstration ? Donc le fichier portable est-il une utopie tant que la taille des types n'est pas garantie d'une plateforme à l'autre ?
Ha bin ok alors, désolé d'avoir été insistant, mais comme
Taurre a écrit:
Salut,
drx a écrit:
Cependant, en continuant mes recherches, je n'arrive pas à trouver de liste exhaustive des type "garantis", je suppose que les (s|u)int(taille)_t en font partie, mais qu'en est-il des autres comme size_t par exemple ?
En fait, la norme ne te garantit pas l'existence des types de taille fixe.
Du coup, il m'a un peu fait flipper. Bon merci pour toutes ces infos, je vais continuer sur ma lancée et finir d'implémenter mes fonctions "j'écris et je lis" à l'épreuve des balles .
Justement, il ne faut pas considérer des long mais des int32 ou des int64 (après tu te fais le typedef qui va bien). Que des types à taille fixe.
C'est une solution, mais il est encore plus simple de concevoir des fonctions qui effectuent des conversions en tableau de char. drx a écrit:
Ai-je été plus clair sur ma démonstration ? Donc le fichier portable est-il une utopie tant que la taille des types n'est pas garantie d'une plateforme à l'autre ?
Non, le fichier portable n'est pas une utopie. Voici un exemple de module fournissant des fonctions de lecture/écriture pour des entiers de 16 et 32 bits au format petit boutiste. io.h
Avec de telles fonctions, le résultat des lecture/écriture sera le même, peut importe la taille des types (sauf pour le type char qui doit avoir une taille de huit bits) et le boutisme utilisé sur les différentes machines (attention toutefois que, pour les entiers signés, cela suppose que les machines cibles utilisent une représentation en complément à deux).
[...] (sauf pour le type char qui doit avoir une taille de huit bits) [...]
Et oui.. sauf... c'est bien là le problème de base. Parce qu'à ce moment là, sérialiser un long, ça marche aussi, bon, SAUF que le long doit faire 32...
Donc si une boite pond un proc au char de 2 octets parce que, mettons l'octet ne sert plus à rien (déjà que...) et que l'UTF16 est devenu natif et remplace l'ascii (par exemple) bin ça marche plus. Donc tu ne fais que supposer que le char fait un octet au lieu d'imposer un 8 bits...
Marc Mongenet a écrit:
[...] Il peut aussi exister des processeurs spécialisés qui n'ont qu'une seule taille de donnée: 32 bits. Dessus, un char fait 32 bits. Et voilà.[...]
Dommage... Bon je cherche la petite bête, avec un peu de mauvaise foi, c'est sûr. Mais du coup, tu peux ptet remplacer tes uchar par des uint8_t .
Bonne continuation.
EDIT. Ceci dit, merci pour le jeu de fonction, même si je préfère me faire les miennes, ça me sera utile à titre d'inspiration .
Lors que tu définis le format de ton fichier, tu définis au passage dans quelle plage de données doivent se trouver les valeurs manipulées. Il y a deux cas qui peuvent éventuellement poser problème :
Si la machine d'accueil utilise des types plus petits en natif, auquel cas, soit tu spécifies que "la machine doit utiliser des types d'au moins [mettez les tailles ici]" et donc tu limites ta portabilité côté exécution. Ou alors, tu t'assures qu'elle utilisera des types plus longs aussi à l'exécution, quitte à ralentir le fonctionnement à coup de typedef en fonction de l'architecture.
Si la machine d'accueil utilise des types plus longs en natif, on pourrait dire "ça risque de poser des problèmes à l'écriture". Sauf qu'en fait, non, si tu as définis des tailles précises pour ton fichier, c'est que tu es sûr que l'exécution ne peut pas générer des valeurs plus grandes quelle que soit l'architecture, donc tout est ok.
- Edité par Ksass`Peuk 20 septembre 2013 à 10:30:54
[...] Il peut aussi exister des processeurs spécialisés qui n'ont qu'une seule taille de donnée: 32 bits. Dessus, un char fait 32 bits. Et voilà.[...]
Dommage... Bon je cherche la petite bête, avec un peu de mauvaise foi, c'est sûr. Mais du coup, tu peux ptet remplacer tes uchar par des uint8_t .
Sur un processeur comme https://en.wikipedia.org/wiki/Super_Harvard_Architecture_Single-Chip_Computer il n'y a manifestement aucune possibilité d'adresser plus finement qu'un byte de 32 bits. Les char font donc 32 bits. Le type uint8_t n'existe probablement pas. Mais ce n'est pas un processeur destiné à faire fonctionner des programmes généralistes. Je ne vois pas de raison pratique d'essayer d'écrire un logiciel portable pour ce genre de processeur. Il y a en revanche de bonnes raisons d'écrire un programme capable de gérer little et big endian, des long de 32 ou 64 bits, des char signés ou pas.
@Marc: Effectivement... Ceci étant, ma remarque était plus une boutade qu'une véritable volonté de démonter les arguments de Taurre, à qui je demande de m'excuser s'il ne l'a pas perçu comme tel, probablement une maladresse de ma part.
p pointera sur un 64 bits chez Marc...Du coup la version big endian n’extraira que les 4 octets de poids les plus forts et écrira 0x00000000 dans le fichier si la valeur est inférieure à 0xFFFFFFFF...
Vous remarquerez quand-même que je me suis empressé d'implémenter les fonctions qui devraient résoudre ce problème en suivant vos conseils... Plus ou moins avec style, c'est certain, mais déjà...
Permettre le bon fonctionnement de mes programmes sur PC indépendamment de l'OS me suffit bien, comme ça les linuxiens pourront aussi profiter de mon super shoot'em up et changer leurs vies .
Sinon, je pense avoir eu les réponses et les explications que j'attendais, merci à vous tous.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Bonhomme !! | Jeu de plateforme : Prototype.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Bonhomme !! | Jeu de plateforme : Prototype.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Bonhomme !! | Jeu de plateforme : Prototype.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Bonhomme !! | Jeu de plateforme : Prototype.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Bonhomme !! | Jeu de plateforme : Prototype.
Bonhomme !! | Jeu de plateforme : Prototype.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Bonhomme !! | Jeu de plateforme : Prototype.