Forum Programmation.c cc, as et ld

Posté par  .
Étiquettes : aucune
0
31
jan.
2007
Bonjour,
Je dois compiler le programme suivant :


#include "stdio.h";

long int factorielle(int n) {
if (n<2) return 1; else return n*factorielle(n-1);
}

int main(int argc, char *argv[]){
int i;
printf("Hello World!\n\n");
for(i=0;i<10;i++)
printf("%i! = %li\n",i,factorielle(i));
return 0;
}


J'utilise les commandes suivantes :


cc -c -S toto.c
as -o toto.o toto.s


Pas de problèmes à ce stade. Par contre l'utilisation de la commande ld s'avère délicate. J'ai finalement réussi à m'en servir de cette façon :


ld -o toto /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtn.o /usr/lib/libc.so toto.o


Aucune erreur n'est apparue mais il m'est impossible d'exécuter le programme résultant (bien sûr j'ai fait un chmod)

Je dois absolument utiliser cc, as et ld.

Quelqu'un pourrait il m'aider ?

Merci d'avance...
  • # il y en manque des options

    Posté par  . Évalué à 3.

    c'est pour ca que rien ne marche

    ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.1 -o toto
    /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o
    -L/usr/lib/gcc-lib/<A COMPLETER> toto.o -lm -lgcc -lc -lgcc
    /usr/lib/crtend.o /usr/lib/crtn.o

    voici un lien pour plus d'info
    http://www.ensta.fr/~gueydan/Poly/Html/node8.html#SECTION034(...)
    • [^] # Re: il y en manque des options

      Posté par  . Évalué à 2.

      Merci, tu as raison, il manquait bien des options. Je garde le lien que tu m'as donné, qui est très intéressant....
  • # Je ne pense pas que ce soit l'erreur...

    Posté par  . Évalué à 2.

    ... mais le
    #include "stdio.h";

    ça s'écrit pas plutôt
    #include <stdio.h>
    ?

    À moins qu'il y ait un truc que je ne connais pas... Je débute seulement.
    • [^] # Re: Je ne pense pas que ce soit l'erreur...

      Posté par  . Évalué à 5.

      #include "stdio.h" -> Va chercher stdio.h dans le répertoire courant puis les répertoires d'inclusion

      #include <stdio.h> -> Va chercher stdio.h dans les répertoire d'inclusion

      Dans notre cas ça ne pose pas de soucis, mais c'est vrai que pour les librairies systèmes on met plutôt #include < >
  • # Un indice :

    Posté par  (site web personnel) . Évalué à 3.

    strace -q -s 64 -f -eprocess gcc toto.c

    Je triche ? non ...
    • [^] # Re: Un indice :

      Posté par  (site web personnel) . Évalué à 3.

      si c'est pour voir comment gcc utilise ld, on peut aussi utiliser gcc -v ou gcc -###
      • [^] # Re: Un indice :

        Posté par  (site web personnel) . Évalué à 2.

        Je viens de voir le lien du premier post, c'est en effet intéressant, j'ai donné cette méthode qui se veut universel pour connaitre rapidement ce que fait un programme (quel sous programme, lib ou fichier il utilise).
        • [^] # Re: Un indice :

          Posté par  . Évalué à 2.

          Merci à tous de vos réponses si rapides ! Je ne connaissais pas la commande strace, elle est géniale : y a plus qu'à lire le résultat. J'ai utilisé les paramétres renvoyés par la commande et ça marche impeccablement

          Merci à tous de vos réponses, on a jamais fini d'apprendre ;-)
  • # Débordement

    Posté par  . Évalué à 1.

    long int factorielle(int n)
    {
        if (n<2)
            return 1;
        else
            return n*factorielle(n-1);
    }
    Le typage est risqué... Pour les grandes valeurs de n, ton programme n'est plus portable. Explications :
    • n est de type int, factorielle(n - 1) est de type long, donc le produit sera de type long (conversions arithmétiques usuelles, 3.6.1.8 du n1124).
    • Lorsque n est grand, au point que factorielle(n - 1) est supérieur à LONG_MAX / n, le produit est donc supérieur à LONg_MAX et déborde donc le domaine de valeurs de long.
    • Le type long est signé, le débordement cause donc un comportement défini par l'implémentation (6.3.1.3 du n1124).
    En langage C, un "comportement défini par l'implémentation" doit être documenté par ton implémentation (compilateur et/ou libc), mais peut être différent d'une implémentation à l'autre (une autre version du même compilateur étant une autre implémentation, comme le même compilateur avec des options différentes).
      En utilisant un autre type (comme unsigned long, voire long long ou stdint.h si tu l'as sous la main), tu augmentes le domaine où ta fonction est utile, mais la gestion d'erreur doit être implémentée, quel que soit le type.
        Proposition (non testée) :
        #include <limits.h>
        
        /*
         * Retourne la factorielle de n.
         * Si la valeur de n! depasse LONG_MAX, la fonction renvoie -1.
         */ 
        long int factorielle(int n)
        {
            long res = 1;
            if (n >= 2)
            {
                res = factorielle(n - 1);
                if (LONG_MAX / n < res || res == -1)
                {
                    /* debordement */
                    res = -1;
                }
                else
                {
                    res *= n;
                }
            }
            return res;
        }
        J'ai juste fait la correction de l'implémentation, mais l'algorithme de calcul présenté ici (application naïve de l'algorithme par récursion non terminale) est largement sous-optimal. Je suppose que le côté algorithmique sera étudié séparément...

      Suivre le flux des commentaires

      Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.