Partage
  • Partager sur Facebook
  • Partager sur Twitter

La LibC des Zéros

Objectif : recoder la libC.

22 novembre 2012 à 12:08:51

Citation : Blodangan

double my_ceil(double x)
{
    return (double)((int)x + 1);
}

Il n'y aurait pas quelques problèmes ? Par exemple, si je fait my_ceil((float)5) il va renvoyer 6.0 alors qu'il devrait renvoyer 5.0.
  • Partager sur Facebook
  • Partager sur Twitter
yjltg.
Anonyme
22 novembre 2012 à 19:47:10

Citation : Taurre

Citation : informaticienzero

Sinon, est-ce que vous pouvez tester le code ci-dessous et dire s'il marche bien chez vous ?



Oui, il fonctionne très bien, mais c'est assez logique puisque tu fais appel à vsprintf et non à my_vsprintf (ligne 16). ^^



Ah oui erreur d'innatention. Et avec my_vsprintf, ça marche ?
  • Partager sur Facebook
  • Partager sur Twitter
22 novembre 2012 à 21:32:54

Citation : informaticienzero

Ah oui erreur d'innatention. Et avec my_vsprintf, ça marche ?



J'ai testé juste par curiosité : sous GNU/Linux (Debian Squeeze) non, sous FreeBSD, oui (mais la valeur de t1 n'est pas affichée).
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
22 novembre 2012 à 21:39:18

C'est bizarre. En fait je pense que ce n'est pas possible de recoder sprintf de manière portable.
  • Partager sur Facebook
  • Partager sur Twitter
23 novembre 2012 à 14:40:38

Citation : informaticienzero

C'est bizarre. En fait je pense que ce n'est pas possible de recoder sprintf de manière portable.



Si, c'est tout à fait possible.
En fait, le seul vrai problème avec les fonctions de la famille printf, ce sont les nombres flottants car je ne pense pas qu'il existe de solution portable pour les afficher avec une précision suffisante (ou, si c'est le cas, je veux bien qu'on me la présente :p ).

Sinon, la solution de la conversion en FILE est juste barbare. :-°
Même à supposer que le premier champ de la structure soit un tableau de char (ce qui n'est pas le cas de la glibc), cela ne garantit en rien du succès de l'opération.
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
23 novembre 2012 à 19:22:51

Citation : Taurre

Citation : informaticienzero

C'est bizarre. En fait je pense que ce n'est pas possible de recoder sprintf de manière portable.



Si, c'est tout à fait possible.

Sinon, la solution de la conversion en FILE est juste barbare. :-°



Comment alors ? Puisque les champs de FILE diffèrent selon l'implémentation. :)
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
23 novembre 2012 à 19:54:36

Pour la famille printf on peut faire comme ça :

int my_printf(const char* fmt, ...)
{
    int ret;
    my_va_list ap;

    my_va_start(ap, fmt);

    ret = my_vprintf(fmt, ap);

    my_va_end(ap);

    return ret;
}

int my_vprintf(const char* fmt, my_va_list ap)
{
    return my_vfprintf(stdout, fmt, ap);
}

int my_fprintf(my_FILE* f, const char* fmt, ...)
{
    int ret;
    my_va_list ap;

    my_va_start(ap, fmt);

    ret = my_vfprintf(f, fmt, ap);

    my_va_end(ap);

    return ret;
}

int my_vfprintf(my_FILE* f, const char* fmt, my_va_list ap)
{
    int ret;
    char str[512] = "";

    ret = my_vsprintf(str, fmt, ap);

    //my_fputs(str, f);

    return ret;
}

int my_sprintf(char* str, const char* fmt, ...)
{
    int ret;
    my_va_list ap;

    my_va_start(ap, fmt);

    ret = my_vsprintf(str, fmt, ap);

    my_va_end(ap);

    return ret;
}

int my_vsprintf(char* str, const char* fmt, my_va_list ap)
{
    int ret = 0;

    /**/

    return ret;
}


Blodangan
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
23 novembre 2012 à 22:39:48

Effectivement c'est une bonne idée. Mais vu comment je m'y suis pris dans mon implémentation ce n'est pas envisageable. Tant pis je me passerai de ces deux fonctions.

@Taurre : paraze a testé pour moi sous ArchLinux, ma fonction my_sprintf a très bien marché. On est d'accord ça relève de l'obfuscation, mais je ne pense pas que l'implémentation de FILE varie entre distributions GNU / Linux si ?
  • Partager sur Facebook
  • Partager sur Twitter
23 novembre 2012 à 23:21:08

Citation : Taurre

En fait, le seul vrai problème avec les fonctions de la famille printf, ce sont les nombres flottants car je ne pense pas qu'il existe de solution portable pour les afficher avec une précision suffisante (ou, si c'est le cas, je veux bien qu'on me la présente :p ).


Je pense que c'est faisable, mais en écrivant plus de code que si l'on écrivait une version pour chaque architecture, donc forcément... En revanche on peut obtenir des résultats très satisfaisant (pas parfait certes... ) grâce à des implémentations portables (cf. nos 2 implémentations si je me souviens bien... ) !
  • Partager sur Facebook
  • Partager sur Twitter
24 novembre 2012 à 12:43:30

Citation : informaticienzero

Comment alors ? Puisque les champs de FILE diffèrent selon l'implémentation. :)



Ben, en ce qui me concerne, j'aurais pensé à une fonction supplémentaire qui chapeauterait vfprintf et vsprintf avec un prototype de ce type :

int vfsprintf(char const *fmt, va_list ap, int type, void *dst);


Dont l'argument type indique si elle doit travailler sur une structure FILE ou sur une chaîne de caractères. Cela allourdi la fonction car cela implique des conditions supplémentaires, mais au moins on évite de dupliquer du code. Aussi, vfprintf et vsprintf peuvent alors être implantées sous forme de macrofonctions :

#define vfprintf(file, fmt, ap) vfsprintf((fmt), (ap), VFSPRINTF_F, (file))
#define vsprintf(str, fmt, ap) vfsprintf((fmt), (ap), VFSPRINTF_S, (str))


Sinon, il ne faut pas perdre de vue que si l'on implante la lib C, on doit définir la structure FILE. ;)

Citation : informaticienzero

@Taurre : paraze a testé pour moi sous ArchLinux, ma fonction my_sprintf a très bien marché. On est d'accord ça relève de l'obfuscation, mais je ne pense pas que l'implémentation de FILE varie entre distributions GNU / Linux si ?



J'aurais dit que cela relève du suicide. :p
Mais, sinon, je n'ai pas d'explication à ce stade... Peut-être que l'implantation a changé depuis la version 2.13 (version installée sous Debian squeeze). M'enfin, de toute manière, écrire directement dans le tampon d'une structure FILE engendre un comportement indéterminé, c'est donc à proscrire (la norme ne précise pas ce qu'il se passe dans un tel cas). ;)

EDIT:

Citation : Holt

Je pense que c'est faisable, mais en écrivant plus de code que si l'on écrivait une version pour chaque architecture, donc forcément... En revanche on peut obtenir des résultats très satisfaisant (pas parfait certes... ) grâce à des implémentations portables (cf. nos 2 implémentations si je me souviens bien... ) !



Si je me rappel bien, il me semble que nos implantations manquaient de précision (notamment pour les grands nombres) comparé aux autres. Maintenant, je pense également qu'une solution portable est envisageable, mais elle sera probablement affreusement lourde (mais je serais quand même curieux d'en voir une :) ).
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
24 novembre 2012 à 12:57:14

Citation : Taurre


Sinon, il ne faut pas perdre de vue que si l'on implante la lib C, on doit définir la structure FILE. ;)



C'est vrai, mais comme mon projet actuel est juste de recoder printf et sa famille et non tout stdio.h, j'ai la flemme. ^^
Mais ton idée de macro est très intéressante, je garde ça sous le coude.
  • Partager sur Facebook
  • Partager sur Twitter
24 novembre 2012 à 13:46:26

Citation : Taurre

M'enfin, de toute manière, écrire directement dans le tampon d'une structure FILE engendre un comportement indéterminé, c'est donc à proscrire (la norme ne précise pas ce qu'il se passe dans un tel cas). ;)



Je me rends compte que ma remarque est complètement à l'ouest puisque tu n'écris pas directement dans le tampon d'un flux. >_<
En fait, je voulais dire qu'exploiter un tableau de char comme une structure FILE est... Heu... de la folie (en fait, je ne comprends même pas pourquoi cela fonctionne dans certains cas). :-°
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
24 novembre 2012 à 17:24:14

Citation : Taurre


Je me rends compte que ma remarque est complètement à l'ouest puisque tu n'écris pas directement dans le tampon d'un flux. >_<
En fait, je voulais dire qu'exploiter un tableau de char comme une structure FILE est... Heu... de la folie (en fait, je ne comprends même pas pourquoi cela fonctionne dans certains cas). :-°



C'est le principe d'un comportement indéterminé : faire l'inverse de ce qu'on pense qu'il va faire. ^^"
  • Partager sur Facebook
  • Partager sur Twitter