質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

4回答

6090閲覧

ヘッダファイルの関数が定義されない

srbk

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2021/07/03 10:01

実現したいこと

変数 x1, x2, x, v を有理数の抽象データ型に変更して、二分法を用いて解を求めるプログラムを作成したい。
ヘッダファイルで関数を定義しているはずなのに、コンパイルすると定義されていない。
特に文法のミス等はないと思うのですが、どこが問題なのでしょうか。

header.h

/*有理数処理のヘッダファイル*/ typedef struct rational { int bunshi ; /* 分子 */ int bunbo ; /* 分母 */ } RATIONAL ; /* 有理数の生成 */ RATIONAL newRational(int n, int d) ; /* 有理数の簡約処理 */ RATIONAL raReduce(RATIONAL v) ; /* 四則演算 */ RATIONAL raAdd(RATIONAL a, RATIONAL b) ; RATIONAL raSub(RATIONAL a, RATIONAL b) ; RATIONAL raMul(RATIONAL a, RATIONAL b) ; RATIONAL raDiv(RATIONAL a, RATIONAL b) ; /* 比較 */ int raEq(RATIONAL a, RATIONAL b) ; int raGt(RATIONAL a, RATIONAL b) ; int raLt(RATIONAL a, RATIONAL b) ; /* 有理数の表示 */ void raPrint(RATIONAL v) ; void raPrintNl(RATIONAL v) ; /* char *raString(char buff[], RATIONAL v) ; */

main.c

#include <stdio.h> #include "header.h" int main(void) { RATIONAL x1, x2, x, v ; RATIONAL eps, c1, c2 ; eps = newRational(2, 1000); c1 = newRational(1, 1) ; c2 = newRational(2, 1) ; x1 = newRational(0, 1); x2 = newRational(1, 1); while (raGt(raSub(x2, x1), eps)) /* (a) x2 - x1 > eps に相当する条件式 */ { x = raDiv(raAdd(x1, x2),c2); /* (b) x = (x1 + x2) / 2.0; に相当する計算式 */ /* 以下は v = x * (x * x + 1) - 1 に相当する式.そのまま使用 */ v = raSub(raMul(x, raAdd(raMul(x, x), c1)), c1); /* x1, x2, x, v の表示 */ printf("x1 = "); raPrint(x1); printf(", x2 = "); raPrint(x2); printf(", x = "); raPrint(x); printf(", v = "); raPrintNl(v); if (raGt(v, x1) /* (c) v > 0 に相当する条件式 */) x2 = x; else x1 = x; } x = raDiv(raAdd(x1, x2),c2); /* (d) x = (x1 + x2) / 2.0; に相当する計算式 */ raPrintNl(x); /* (e) 求まった解 x の表示 */ return 0; }

エラーコード

/tmp/cc5jtIoE.o: 関数 main' 内: main.c:(.text+0x13): newRational' に対する定義されていない参照です
main.c:(.text+0x26): newRational' に対する定義されていない参照です main.c:(.text+0x39): newRational' に対する定義されていない参照です
main.c:(.text+0x4c): newRational' に対する定義されていない参照です main.c:(.text+0x5f): newRational' に対する定義されていない参照です
main.c:(.text+0x7b): raAdd' に対する定義されていない参照です main.c:(.text+0x8d): raDiv' に対する定義されていない参照です
main.c:(.text+0xa4): raMul' に対する定義されていない参照です main.c:(.text+0xb6): raAdd' に対する定義されていない参照です
main.c:(.text+0xc8): raMul' に対する定義されていない参照です main.c:(.text+0xda): raSub' に対する定義されていない参照です
main.c:(.text+0xf9): raPrint' に対する定義されていない参照です main.c:(.text+0x114): raPrint' に対する定義されていない参照です
main.c:(.text+0x12f): raPrint' に対する定義されていない参照です main.c:(.text+0x14a): raPrintNl' に対する定義されていない参照です
main.c:(.text+0x15d): raGt' に対する定義されていない参照です main.c:(.text+0x186): raSub' に対する定義されていない参照です
main.c:(.text+0x198): raGt' に対する定義されていない参照です main.c:(.text+0x1b3): raAdd' に対する定義されていない参照です
main.c:(.text+0x1c5): raDiv' に対する定義されていない参照です main.c:(.text+0x1d5): raPrintNl' に対する定義されていない参照です
collect2: error: ld returned 1 exit status

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2021/07/03 10:29 編集

関数 RATIONAL newRational(int n, int d) はどこにあるんですか? (他のも) ヘッダファイルの関数が定義”されない”じゃなく、"していない"のでは?
guest

回答4

0

すでに回答もありますが、敢えて強調しておきます。
「宣言」と「定義」は違うもの(こと)です。この言葉を混同している時点で「文法のミス」です。
質問のヘッダファイルで行っているのは「宣言」です。定義ではありません。

「宣言」は、こういう関数がどこかにある、という情報です。コンパイルに必要なのは、関数の名前、戻り値の型、引数リストの引数型(仮引数名を書いてもいいが無視される)で、そういう情報が(それだけが)書かれています。(これらのセットを関数のシグニチャともいいますがそれは置いといて)。
宣言は、互いに矛盾さえしなければ同じ内容の宣言がプログラム中に何回現れても構いません。

「定義」は、関数が実際に何をするのかの記述です。宣言と同じ情報に、さらに{ }の中に関数の振る舞いを記述しています。これは、プログラム全体のどこかに一度だけ記述されている必要があります。記述はソースのどこかにあるかも知れませんし、ライブラリとして別にコンパイルされた結果を利用するかも知れませんが。また、定義は複数記述されていてはいけません。

今回は、宣言しか与えていませんから、「定義がない」と言われています。何らかの方法で、定義を教えてやってください。

投稿2021/07/03 11:02

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ヘッダファイルで関数の宣言を行っているとありますが、ある意味、正しく、また間違ってます。
ヘッダファイルで、例えば、RATIONAL newRational(int n, int d) ;とあるのは、 newRationalという関数が、この形式であると宣言しているだけで、中身がどうなってるかまでは、定義してません。
関数の実体が別に必要です。

この関数は、どこかのライブラリでしょうか?
それならば、コンパイル時のオプションとして、ライブラリ指定が必要です。
そうでなければ、実体の定義が必要です。

投稿2021/07/03 10:09

pepperleaf

総合スコア6385

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

itagagaki

2021/07/03 10:17

「ヘッダファイルで関数を定義している」と書かれていますね。 これは正しくは「宣言」しているですね。 この方はまず定義と宣言の正しい理解が必要だなと思いました。 それと細かいようですが、ライブラリ指定はコンパイル時ではなくリンク時ですね。 このエラーはコンパイル時エラーではなくリンク時エラーです。これも初学者にありがちなのですが、それの区別もこの方には必要だなと思いました。
pepperleaf

2021/07/03 12:37

確かにリンク時ですね。 ただ、最初から、コンパイルとリンクを別々に行う事は、あまり無いのでは? もっとも自分もリンクのつもりでコンパイルと言ってみたり、、とか注意が必要なのは間違いない。 makeだと、ビルドかな?
guest

0

header.hで宣言している各関数(newRationalなど)の定義(実体、中身)はどこにありますか?

header.h内に書かれている

C

1RATIONAL newRational(int n, int d) ;

これは関数の「宣言」です。「定義」ではありません。

関数の「定義」とは

C

1RATIONAL newRational(int n, int d) 2{ 3 //何かの処理 4 return <RATIONAL型の値>; 5}

といった形の関数の実体のことを言います。

関数やデータの実体を含む各ソースコードファイルは、それをコンパイルすることによってオブジェクトファイルが生成されます。

あるオブジェクトファイルから呼び出されている関数は、必ずしもそのオブジェクトファイルの中に無くてもよく、他のオブジェクトファイルにあってもかまいません。それを依存関係という言い方をします。

必要なオブジェクトファイルをすべてリンクして依存関係を完全に解消することによって、実行可能なファイルが出来上がります。このリンク時には、予め作られたオブジェクトファイルを組み合わせたライブラリファイルを与えることもできます。

main.cからはnewRationalなどを呼び出していますが、その実体はmain.cの中には無いですね。それでもコンパイルができるのはnewRationalなどの宣言がheader.hにあり、それをmain.cにインクルードしているからです。それによってコンパイルは成功してオブジェクトファイルが生成されているのだと思いますが、そのオブジェクトファイルはnewRationalなどを他のオブジェクトファイルまたはライブラリファイルに依存していることになります。

なので、実行可能なファイルを作り上げるには、リンカで、main.cから作られたオブジェクトファイルと、newRationalなどの実体を持つ他のオブジェクトファイルまたはライブラリファイルとをリンクさせる必要があります。

表示されているエラーは、このリンク時に「main.cが依存しているnewRationalなどの実体がどこにも無いよ」という意味です。

したがって、解決するべきなのは、その実体がどこにあるのか(たとえば自分が用意した他のCソースコードに実体があるのか、あるいはライブラリファイルとして用意されているのか)を把握することと、それをリンカに対してもれなく指定することです。

他の方からも既にいろいろ回答がありますが、理解を助ける意味で少し詳しく書きました。

投稿2021/07/03 16:12

itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ヘッダファイルで定義するのは、プロトタイプ宣言です。
どういうふうに使うか、という雛形を示しているだけで、実際にナカミまで定義してません。

コンパイル時には、これらの雛形を見ながら、こういう関数があるはず、ということでコンパイルを進めていきますが、リンカによるリンク時に、それらの実体がないと、エラーになります

まさにそういうエラーが出ています。

これをどうにかするためには、それらの関数を定義しているソースファイルを一緒にコンパイルする、か、
それらの関数を実装しているライブラリファイルをリンク時に指定する、ことです

投稿2021/07/03 11:02

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問