2012-08-22 3 views
2

J'ai écrit un exemple de programme sur les structures. J'ai écrit 3 fichiers source et un fichier 1 en-tête. Ceci est la source complète du programme:Quel est le problème avec ce code C?

main.c:

#include <stdio.h> 
#include <stdlib.h> 
#include "fish.h" 

/* 
struct fish 
{ 
    const char *name; 
    const char *species; 
    int teeth; 
    int age; 
}; 
*/ 

/* 
void catalog(struct fish f) 
{ 
    printf("%s is a %s with %i teeth. He is %i.", 
      f.name, f.species, f.teeth, f.age); 
} 


void label(struct fish f) 
{ 
    printf("Name: %s\n", f.name); 
    printf("Species: %s\n", f.species); 
    printf("Teeth: %i\n", f.teeth); 
    printf("Age: %i\n", f.age); 
} 
*/ 

int main() 
{ 
    struct fish snappy = {"Snappy", "Piranha", 69, 4}; 
    catalog(snappy); 
    label(snappy); 

    return 0; 
} 

label.c:

#include "fish.h" 

void label(struct fish f) 
{ 
    printf("Name: %s\n", f.name); 
    printf("Species: %s\n", f.species); 
    printf("Teeth: %i\n", f.teeth); 
    printf("Age: %i\n", f.age); 
} 

catalog.c:

#include "fish.h" 

void catalog(struct fish f) 
{ 
    printf("%s is a %s with %i teeth. He is %i.", 
      f.name, f.species, f.teeth, f.age); 
} 

J'ai aussi écrit une Fichier Make:

fish.o: main.c label.c catalog.c fish.h 
    gcc -c main.c label.c catalog.c 
fish: fish.o 
    gcc fish.o -o fish 

Je compilez le programme cmd:

make fish 

Il dit:

gcc -c main.c label.c catalog.c 
label.c: In function 'label': 
label.c:5:5: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default] 
catalog.c: In function 'catalog': 
catalog.c:5:5: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default] 
cc fish.o -o fish 
cc.exe: error: fish.o: No such file or directory 
cc.exe: fatal error: no input files 
compilation terminated. 
make: *** [fish] Error 1 

Si je supprime les commentaires dans le main.c et de la compilation, ça marche, mais quand je me suis cassé en petites pièces comme mentionné ci-dessus, cela ne fonctionne pas.

Quel est le problème?

+0

Les avertissements de compilation sont corrigés en incluant '#include ' dans les fichiers qui utilisent 'printf()'. Ne prenez pas la peine de lutter avec des alternatives; il suffit d'inclure l'en-tête standard. –

+0

merci Jonathan, ça marche. Bien. – 0xEDD1E

Répondre

2

Cette règle de liaison:

fish: fish.o 
    gcc fish.o -o fish 

est approprié pour la construction d'un programme fish à partir d'un seul fichier objet fish.o (qui est vraisemblablement compilé à partir de fish.c).

Vous avez besoin d'une autre règle:

OBJECTS = main.o label.o catalog.o 

fish: ${OBJECTS} 
    ${CC} -o [email protected] ${OBJECTS} 

Vous pouvez ajouter ${CFLAGS} et ${LDFLAGS} et ${LDLIBS} (ou ${LDLIBES}) à la ligne de liaison, selon le cas, si vous voulez, mais pour des programmes simples, ce que j'ai montré suffit. Vous n'avez pas besoin de dire make comment convertir main.c en main.o; il le sait déjà. Il utilisera une règle telle que:

%.o: %.c 
    ${CC} -c ${CFLAGS} $< 

pour créer le fichier .o à partir du fichier .c correspondant. (Ceci est la GNU Make notation, et d'autres make POSIX versions classiques de make utiliser une alternative, mais vaguement notation équivalente .c.o: en place de %.o: %.c.)

Si vous ne me dérange pas de compiler toutes les sources à chaque fois, vous pouvez utiliser une règle similaire:

SOURCES = main.c label.c catalog.c 

fish: ${OBJECTS} 
    ${CC} ${CFLAGS} -o [email protected] ${SOURCES} 

Cette fois-ci, ${CFLAGS} est pratiquement obligatoire (si vous souhaitez vous en tirer sans elle dans votre programme d'échantillonnage bare-bones).


Notez que make est difficile; les lignes de commande telles que les lignes ${CC} doivent commencer par TAB; les blancs ne le feront pas.

+0

il est dit: makefile: 4: *** séparateur manquant. Arrêtez. – 0xEDD1E

+2

Garantissez $ {CC} -o $ @ $ {OBJECTS}. N'utilisez pas d'espace. – Jeyaram

4

Vous aurez besoin de compiler tous les fichiers .c ensemble afin que vous puissiez utiliser vos fonctions définies dans label.c et catalog.c dans main.c.

Vous pouvez le faire en une seule étape en utilisant gcc:

gcc main.c label.c catalog.c -o fish 

Ceci compile chaque fichier source individuelle et produire object files, qui seront reliés entre eux pour produire votre exécutable. Les erreurs que vous voyez se produisent pendant la phase de liaison, lorsque gcc essaie de trouver les fonctions catalog et label.

3

gcc main.c -o fish ne compile que main.c. main.c ne sait pas sur label.c. Il sait seulement qu'il doit appeler une fonction appelée "label", qui est définie ailleurs. Ensuite, l'éditeur de liens regarde tous les fichiers objets générés, et les « liens » en un seul exécutable:

gcc main.c -c 
gcc label.c -c 
gcc catalog.c -c 
ld main.o label.o catalog.o -o fish 

Ceci est la version explicite de

gcc main.c label.c catalog.c -o fish 
+0

Vous ne devriez pas utiliser 'ld' raw pour lier un programme C; utilisez 'gcc' pour qu'il fournisse le bon code de démarrage (classiquement, quelque chose comme' crt0.o') et spécifie la bibliothèque C automatiquement. –