web-dev-qa-db-ja.com

Cコンパイル-「未定義の参照」?

信頼できるデータ転送プロトコルを作成しており、関数のプロトタイプを持っています

_void tolayer5(int, char data[]);
_

structs

_struct msg {
  char data[20];
};

struct pkt {
   int seqnum;
   int acknum;
   int checksum;
   char payload[20];
};
_

そして、この形式で関数を呼び出すと:

_tolayer5(A, packet.payload);
_

Aintで、_packet.payload_が_struct pkt_である場合、「'tolayer5(int, char*)'への未定義の参照」というエラーが表示されます。私はここで何が欠けていますか?

_void tolayer5(int AorB, char data[])
{
  int i;
  if (TRACE>2)
  {
     printf("TOLAYER5: data received:");
     for (i=0; i<20; i++)
        printf("%c",data[i]);
     printf("\n");
  }
}
_

元の問題を手伝ってくれてありがとう! :)しかし、それを修正しようとしたときに、配列内の文字を間違ってアドレス指定することに関係していると思われる無限ループに遭遇しました(このようにCを実行してからしばらく経ちました)。無限ループを作成している場所を見つけるのを手伝ってもらえますか?

上記のコードを現在作業中のコードに更新しました。主な変更点は私の機能にあったことに注意してください。

_void tolayer5(int AorB, char data[])
_

そして、関数内の次の行:printf("%c",msgReceived.data[i]);これは今だけです:

_printf("%c",data[i]);
_
8
Katie Jurek

tolayer5()を実装するobjファイルとリンクする必要があるようです

更新:関数宣言が実装と一致しません:

      void tolayer5(int AorB, struct msg msgReceived)
      void tolayer5(int, char data[])

したがって、コンパイラーはそれらを2つの異なる関数として扱います(c ++を使用しています)。また、main()で呼び出したものの実装を見つけることができません。

12
tristan

いくつかの他の人が述べたように、これはリンクエラーです。この関数が呼び出されているコードのセクションは、この関数が何であるかを知りません。ヘッダーファイルで宣言するか、独自のソースファイルで定義するか、同じソースファイルで定義または宣言する必要があります。

編集:古いバージョンのC、C89/C90では、関数宣言は実際には必要ありませんでした。したがって、関数を使用しているファイルのどこにでも、呼び出しやコンパイラが宣言を推測した後でも、定義を追加するだけで済みます。例えば、

int main()
{
  int a = func();
}

int func()
{
   return 1;
}

ただし、これは今日の良い習慣ではなく、ほとんどの言語、たとえばC++では許可されません。使用しているのと同じソースファイルで関数を定義するのをやめる1つの方法は、ファイルの先頭で宣言することです。したがって、前の例は代わりにこのようになります。

int func();

int main()
{
   int a = func();
}

int func()
{
  return 1;
}
1
dsell002

Tolayer5関数をプロトタイプとして宣言するか、それを使用するファイルの早い段階で完全な関数定義を定義してください。

1
Phillip Ngan