2011-01-24 8 views
2

Cはメイクファイルとインクルード文を持っているので、あなたは特異なモンスターサイズのファイルを持たないので、コードを機能的に分解する必要があります。したがって、私が正しいとすれば、ヘッダーを作成して正しく作成すれば、.cファイル間で関数呼び出しを行うことができます。C:ヘッダーファイルと質問が含まれています。助けが必要!

私はそれをやろうとしていますが、残念ながらエラーが発生しています。

ファイル1)test.cの:

#include<stdio.h> 
#include"suc.h" 

main() 
{ 
    printf("Hello World\n\n"); 
    printf("This is the number: %d \n\n", suc(6)); 
} 

ファイル2)メイク:

ファイルは、次の内容を持っている

CC=gcc 
CFLAGS=-c -Wall 

test: suc.o 
$(CC) -Wall -o test test.c 

suc.o: suc.c 
$(CC) $(CFLAGS) suc.c 

ファイル3)suc.hを

#ifndef SUC_H_GUARD 

#define SUC_H_GUARD 

// returns the successor of i (i+1) 
int suc(int i); 


#endif 

ファイル4)suc.c

#include "suc.h" 

int suc(int i) 
{ 
return i + 1; 
} 

私は私が手(-Bを作る)トップますしかし

gcc -c -Wall suc.c 
gcc -Wall -o test test.c 
test.c:7: warning: return type defaults to 'int' 
/tmp/cc/7w7qCJ.o: In function 'main': 
test.c: (.text+0x1d): undefined reference to 'suc' 
collect2: ld returned 1 exit status 
make: *** [test] Error 1 

をこの単一のファイルプログラムがうまく動作 A): の両方が期待される結果を生みます!

#include<stdio.h> 

main() 
{ 
    printf("Hello World\n\n"); 
printf("This is the number: %d \n\n", suc(6)); 
} 

int suc(int i) 
{ 
return i + 1; 
} 

B)、元のすべてのファイルが、test.cのに次の変更を伴う:

#include<stdio.h> 
#include"suc.h" //suc() is still defined b/c suc.h is included 

main() 
{ 
    printf("Hello World\n\n"); 
printf("This is the number: %d \n\n", 4); //HERE! -> no function call 
} 

ヘルプ、してくださいとあなたに感謝! エラーメッセージが何を伝えようとしているのかよくわかりません。テストを構築するとき、あなたがsuc.oをリンクしていない

+3

技術的には、 "C"にはメイクファイルはありませんが、実行されるオペレーティングシステムにはメイクファイルがあることがあります。 –

答えて

4

ソースファイルをオブジェクトファイルに個別にコンパイルし、オブジェクトファイルをリンクして実行可能ファイルtestを取得する必要があります。

だからあなたが必要とする:

<tab>はタブで
CC=gcc 
CFLAGS=-c -Wall 

test: test.o suc.o 
<tab>$(CC) -Wall -o test test.o suc.o 

test.o: test.c 
<tab>$(CC) $(CFLAGS) test.c 

suc.o: suc.c 
<tab>$(CC) $(CFLAGS) suc.c 


あなたの現在のメイクファイルでの問題はここにある:

test: suc.o 
    $(CC) -Wall -o test test.c 

testsuc.oに依存し、あなたがする必要があるtestを取得すると言うた:

$(CC) -Wall -o test test.c 

が、そのコンパイルを見て/リンク行には、suc関数が定義されているソース/オブジェクトファイルは含まれていません。

あなたが追加することができsuc.oとして:

$(CC) -Wall -o test test.c suc.o 

しかし、ので、あなたは、あなたのメイクファイルがsuc.oを再生成しますのみsuc.cファイルを変更してもtestを再生成する必要がありますが、testを再生するためにあなたが言う悪いと考えられていますtest.cは変更されていないと思われるかもしれません。

+0

多くのバージョンのmakeでは、このMakefileの最初の4行だけが必要であることに注意してください。 –

2

両方の最終test実行可能ファイルにそれらをリンク、オブジェクト・ファイルにtest.csuc.cの両方をコンパイルします。このメイクファイルは動作するはず

(あなたがルール内のタブをスペースに置き換えることを確認してください):

CC=gcc 
CFLAGS=-c -Wall 

.PHONY: all 
all: test 

test: test.o suc.o 
    $(CC) -Wall test.o suc.o -o test 

test.o: test.c 
    $(CC) $(CFLAGS) test.c 

suc.o: suc.c 
    $(CC) $(CFLAGS) suc.c 
1

この依存関係の行は失敗します。

test: suc.o 
    $(CC) -Wall -o test test.c 

あなたはSUCとリンクしていないため。 O(そして、ところで、テストはsuc.oとtest.oによって異なります)

あなたの行は次のようになります。

test: test.o suc.o 
    $(CC) -Wall -o test test.o suc.o 

test.o : test.c 
    $(CC) -c test.c 
+0

あなたの解決策では、 'suc.c'が変更された場合、' test.c'も再コンパイルされます。 – codaddict

+0

@codaddict - fixed – KevinDTimm

1
gcc -c file.c 

ファイルfile.oをobjectにfile.cをコンパイルします。

gcc -o test test.c 

は、実行可能ファイルにコンパイルとリンクtest.cます。

しかし、あなたは

gcc -c test.c 
gcc -c sic.c 
gcc -o test test.o sic.o 

いずれか

gcc -o test test.c sic.c 
+0

'-c'フラグがありません – codaddict

+0

@codeaddict:right :) – ruslik

2
のいずれかを記述する必要がありますので、実行可能ファイルを作成するために、あなたは、あなたのケース suc.oには、必要なすべてのオブジェクトファイルとリンクしなければなりません

C リンカーがかなりばかげているので、suc.o(最初のコンパイルステップで生成)にコンパイル済みコードを含めるようにリンカーに指示する必要があります。それは魔法による関数の実装については知らない。 (それも、それはこの方法であることをたまに便利です!)

が動作するはずこれでコンパイルの第2工程を行う:

gcc -Wall -o test test.c suc.o 
+0

あなたの解決策では、' suc.c'が変更された場合 – codaddict

+0

@codaddict:現代のコンピュータの速度を考えれば大きな問題ではありません。また、動作させるための最小限の変更でもあります。 –

4

をお使いの場合は、次の2つのファイル「suc.c」と "コンパイルtest.c "を2つの異なるオブジェクトファイル、" suc.o "と" test.o "に変換します。ただし、プログラムをリンクするときは、オブジェクトファイルを1つしか指定しないため、リンカが定義または "suc"関数を見つけることができません。あなたはmakeファイルを次のようなものに修正する必要があります:

suc.o: suc.c 
    $(CC) $(CFLAGS) suc.c 

test.o: test.c 
    $(CC) $(CFLAGS) test.c 

test: suc.o test.o 
    $(CC) -Wall -o test suc.o test.o 

幸運を祈る!

+0

私はこの順序を試みました他のもの(test:suc.o test.oは最後に最初に反対しています)、suc.oをコンパイルするように見えます。最初のものをコンパイルしようとしているだけで、残りの部分を再帰的にコンパイルしようとします。 ? – Zigu

+0

@Zigu: 'test.o'が存在しないか、' test.c'よりも古いときにコンパイルします。 – reinierpost

2

「suc.o」とのリンクを示すすべての回答に加えて、return type defaults to 'int'という警告は、main()関数の戻り値の型を宣言することを怠ったことを伝えています。すでに確かにここに十分な答えがあります

int main(int argc, char *argv[]) 
0

正しい定義は何かのようなものです。もう1つは傷つけることはできません。メイクは(一般的に)かわいいです。それは、標準のビルドルールの知識だ使用して、単一の行に至るまで、あなたのMakefileを単純化してみましょう:それは、一般的にそれらを推測することができるので

 
test: test.o suc.o 

は、それを簡単なビルドルールを与えて気にしないでください。 (私はgnu makeについて考えていますが、ほとんどのバージョンではそうではありません)。

さらに、実行ファイルの名前を変更することを検討してください。 "test"という名前は混乱を招く原因です。実行しようとすると、シェル組み込み関数または/ bin/testのいずれかが予期せず取得されるためです。

+0

OPの前にmakeの組み込み機能について話し始めるのが時期尚早ではないようですどのようなものがあるか理解していますか? – KevinDTimm

+0

@KevinDTimm異なる教育法、そうだと思います。私は、学習するときに詳細を隠しておく方が簡単だと分かり、暗黙のルールに依存してMakefileを単純化することでそれが実現します。 –