掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.23730

ヘッダおよびプログラムの構造
投稿者---ひろし(2005/10/20 00:28:14)


OS Mac osX
開発 Xcode
コンパイラ gcc

初心的な質問ですみませんが、道に迷っています。
c言語で使う関数は、
ヘッダ内、プロトタイプ宣言のみされていますが、
なぜ、プロトタイプ宣言のみで具体的に関数が動くのでしょうか。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:ヘッダおよびプログラムの構造 23731 まきじ 2005/10/20 00:49:35
<子記事> Re:ヘッダおよびプログラムの構造 23745 sakura 2005/10/20 14:14:10


No.23731

Re:ヘッダおよびプログラムの構造
投稿者---まきじ(2005/10/20 00:49:35)


>ヘッダ内、プロトタイプ宣言のみされていますが、
>なぜ、プロトタイプ宣言のみで具体的に関数が動くのでしょうか。

ライブラリ化されているからです。


この投稿にコメントする

削除パスワード

No.23792

Re:ヘッダおよびプログラムの構造
投稿者---ひろし(2005/10/23 01:02:03)


まきじさんありがとうございます。お待たせしてすみません。
皆さんが認識している"ライブラリ"とは"ヘッダの集まり"とどのような違いがあるのでしょうか?。
気分屋さんの"関数の本体"という表現も気になります。
手探り中で質問が抽象的ですがお願いします。


この投稿にコメントする

削除パスワード

No.23793

Re:ヘッダおよびプログラムの構造
投稿者---まきじ(2005/10/23 01:06:28)


>皆さんが認識している"ライブラリ"とは"ヘッダの集まり"とどのような違いがあるのでしょうか?。

ヘッダに宣言された関数などの実装が記述されているのがライブラリ(*.lib )です。
メモ帳などで開いてもソースは見れないですが・・・


この投稿にコメントする

削除パスワード

No.23837

Re:ヘッダおよびプログラムの構造
投稿者---ひろし(2005/10/26 01:35:50)


まきじさんありがとうございました。
Mac内.libは無いようですが(stdio.hすら可視ファイルは無い様ですが)、構造が分かるにつれて、視野が広がります

なぜヘッダを呼び出したときに、ヘッダ内で
__〇〇〇_H_
の様にアンダーラインと大文字でマクロの真偽が問われるのか?
と言った疑問も残っていますが、
読みかけの本に幸い少し載ってるようなので粘ります。
(分からなかった場合は再度お世話になりますが、お願いします)




この投稿にコメントする

削除パスワード

No.23844

Re:ヘッダおよびプログラムの構造
投稿者---nop(2005/10/26 11:37:40)


・プリプロセス
・分割コンパイル
・標準ライブラリ

この辺りを調べてみると、幸せになれるかもしれません。


>なぜヘッダを呼び出したときに、ヘッダ内で
>__〇〇〇_H_
>の様にアンダーラインと大文字でマクロの真偽が問われるのか?

・インクルードガード

辺りで調べてみると、幸せになれるかもしれません。


この投稿にコメントする

削除パスワード

No.23943

Re:ヘッダおよびプログラムの構造
投稿者---ひろし(2005/11/02 07:09:22)


インクルードガード
プリプロレス
標準ライブラリ
分割コンパイル
全て既知しているものでした(頭の中で美味く噛み合っていなかったようで)
しかし(このスレッドで)知識を頂いてc全体がようやく見えてきました。
nopさん・まきじさん、本当にありがとうございます。

ここでもう1つ質問を。
cで、他言語で書かれた関数を使う事はできないものなのでしょうか?


この投稿にコメントする

削除パスワード

No.23944

他言語同士ではダメ?
投稿者---ひろし(2005/11/02 07:17:11)


c++プロジェクトで
main.c
sub.c++
sub.h(++)
これら三つのファイルを作りました。
main.cにmain関数がある、簡単な引数やり取り&出力プログラムなのですが,『ZeroLink: unknown symbol '_panda'』でエラーになってしまいます。

-- main.c --
#include <stdio.h>

int main(void)
{
  int a=10;
  panda(a);
  return 0;
}


-- panda.h --
#ifndef _PANDA_H_
#define _PANDA_H_

int panda(int);

#endif _PANDA_H_


-- panda.c++ --
#include <iostream.h>

int panda(int x)
{
  cout << x;
  return x;
}



この投稿にコメントする

削除パスワード

No.23945

Re:他言語同士ではダメ?
投稿者---Blue(2005/11/02 08:57:02)


参考
分割コンパイル


この投稿にコメントする

削除パスワード

No.23946

Re:他言語同士ではダメ?
投稿者---かずま(2005/11/02 09:58:30)


> main.cにmain関数がある、簡単な引数やり取り&出力プログラムなのですが,
> 『ZeroLink: unknown symbol '_panda'』でエラーになってしまいます。
panda.h の中を  extern "C" int panda(int);  にして、
main.c と panda.c++ の両方に #include "panda.h" を追加する。



この投稿にコメントする

削除パスワード

No.23947

Re:他言語同士ではダメ?
投稿者---かずま(2005/11/02 12:04:51)


> panda.h の中を  extern "C" int panda(int);  にして、

訂正します。

#ifdef __cplusplus
extern "C"
#endif
int panda(int);

または、

#ifdef __cplusplus
extern "C" {
#endif

int panda(int);

#ifdef __cplusplus
}
#endif



この投稿にコメントする

削除パスワード

No.23952

Re:他言語同士ではダメ?
投稿者---ひろし(2005/11/02 23:43:53)


Blueさん、かずまさんありがとうございます。
すみません!。
main.cの方に『#include "panda.h"』
の記入を忘れていました。ごめんなさい。
Blueさんご迷惑かけました。(読みました)

さて、かずまさんの補助のおかげでエラーが消えました。
少量の追加ですが、疑問が色々です。
c++書で分割コンパイルを読んでいるので、もう少し待っていて下さい。

とりあえず今の疑問を上げると
1、panda.c++にもpanda.hをインクルードする理由
2、__cplusplusのマクロ宣言元と意味(何と対応しているのか)
3、extern "C"


この投稿にコメントする

削除パスワード

No.23959

Re:他言語同士ではダメ?
投稿者---まきじ(2005/11/04 00:33:13)


>2、__cplusplusのマクロ宣言元と意味(何と対応しているのか)

C++ のソースをコンパイルした時に定義されます。

>3、extern "C"

C リンケージを持たせます。
extern "C" は C++ から Cで作成された関数を使いたい時に使います。

# C から C++ で作成された関数を呼び出す事はできないかと。
# 私の勘違いだったら、すいません。

参考: http://www1.kcn.ne.jp/~robe/cpphtml/html03/cpp03047.html


この投稿にコメントする

削除パスワード

No.23960

Re:他言語同士ではダメ?
投稿者---YuO(2005/11/04 01:00:29)


># C から C++ で作成された関数を呼び出す事はできないかと。

呼び出せますよ。

関数の名前だけの問題なのですが,
呼び出される側がextern "C"修飾を行うと,
C++でコンパイルされた関数の名前がCの規則で作られるため,
Cからでも呼び出せるようになります。

まぁ,大域名前空間直下にない関数は呼び出せませんが……。


この投稿にコメントする

削除パスワード

No.23987

Re:他言語同士ではダメ?
投稿者---ひろし(2005/11/06 12:30:42)


まきじさん・YuOさんありがとうございます。
cリンケージ良く理解できました。(読んでいるC++書には結局未記載でしたが)
各ソースに多重インクルードかも、と思われるようなインクルードがなされる理由も理解できました。
ただ、なぜsub.c++にインクルードが無い場合、『完全に』エラーになるのかは少しだけ疑問が残ります。
何はともあれ、解決したように思われます。
いつも濃密な補助をありがとうございます。


この投稿にコメントする

削除パスワード

No.23988

Re:他言語同士ではダメ?
投稿者---まきじ(2005/11/06 13:12:16)


>ただ、なぜsub.c++にインクルードが無い場合、『完全に』エラーになるのかは少しだけ疑問が残ります。

main.c で panda.h が include されていないと
プロトタイプ宣言がされていないので
コンパイルエラーとなります。
よって main.c に include する必要があります。

panda.cpp は C++ の関数 panda を定義してますが
コンパイル後の関数名を C 言語 に合わせる為に
extern "C" として宣言する必要があります。
よって panda.cpp にも include する必要があります。


この投稿にコメントする

削除パスワード

No.23989

Re:他言語同士ではダメ?
投稿者---とおり(2005/11/06 13:36:22)


わかりにくいので、pandaかsubか統一して下さい。>ひろしさん

>panda.cpp は C++ の関数 panda を定義してますが
>コンパイル後の関数名を C 言語 に合わせる為に
>extern "C" として宣言する必要があります。
>よって panda.cpp にも include する必要があります。

要は、panda.cppにpanda.hをincludeしないと、panda.cppのコンパイルでは
extern "C"指定が見えないのでC++関数としてコンパイルされてしまうと。
だけど、main.cからはC関数として呼び出そうと(リンクしようと)している
ので、一致せずリンクエラー。


この投稿にコメントする

削除パスワード

No.23990

Re:他言語同士ではダメ?
投稿者---かずま(2005/11/06 14:08:18)


> ただ、なぜsub.c++にインクルードが無い場合、『完全に』エラーになる
> のかは少しだけ疑問が残ります。
> 何はともあれ、解決したように思われます。
疑問が残るようでは解決したとはいえません。
sub.c++ にインクルードファイルがなくても、panda に対して、
extern "C" が指定されていれば、エラーにならないはずです。
main.c は C ですから、int を返す関数を呼び出す場合、
インクルードファイルが無くても、エラーになりません。

$ cat main.c
int main(void)
{
        int a = 10;
        panda(a);
        return 0;
}
$ cat sub.c++
#include <iostream>

extern "C" int panda(int x)
{
        std::cout << x << '\n';
        return x;
}
$ gcc -c main.c
$ g++ -c sub.c++
$ g++ main.o sub.o
$ ./a.out
10
$

----------------------------------------------------------------------
gcc/g++ なら、extern "C" が無くてもリンクする方法もあります。

$ cat main.c
int main(void)
{
        int a = 10;
        _Z5pandai(a);
        return 0;
}
$ cat sub.c++
#include <iostream>

int panda(int x)
{
        std::cout << x << '\n';
        return x;
}
$ gcc -c main.c
$ g++ -c sub.c++
$ g++ main.o sub.o
$ ./a.out
10
$



この投稿にコメントする

削除パスワード

No.23991

Re:他言語同士ではダメ?
投稿者---ひろし(2005/11/06 23:45:56)


まきじさん・とおりさん・かずまさん、最後までほんとにありがとうございます。
(あまりにツリーが長くなって怒られそうで心配です、管理人さんすみません)
とおりさん、読みにくい中をわざわざすみません。pandaに統一します。

さて、気付きました。
『exterm "C"』はこの一行で、ひとくくりでは無く、
関数の宣言定義の前に添える事が正しい文法なんですね。
(気付かずにちょっと違う次元でいろいろ考えていたので恥ずかしいです)

『ヘッダのプロトタイプ宣言にこの文法がくっ付いていればエラーが無く、
 他言語関数の実装にこの文法がくっ付いていてもエラーがなくなる。』

では、なぜ、
panda.c++にcリンケージを添えると、
  panda.c++にpanda.hのインクルードと
  panda.h  での__cplusplusマクロの真偽が不必要で。
panda.hにcリンケージを添えると、
  panda.c++にpanda.hのインクルードと
  panda.h  での__cplusplusマクロが必要なのでしょうか。

簡潔な質問は、
プロトタイプ宣言にcリンケージをもたせるのと、
関数の宣言定義にcリンケージをもたせるのはどこが違うのでしょうか?
本当に長いツリーすみません。ありがとうございます。



この投稿にコメントする

削除パスワード

No.23992

Re:他言語同士ではダメ?
投稿者---かずま(2005/11/07 03:35:21)


> プロトタイプ宣言にcリンケージをもたせるのと、
> 関数の宣言定義にcリンケージをもたせるのはどこが違うのでしょうか?
// --- panda.c++
#include <iostream>

int panda(int x);
int panda(int x);
int panda(int x) { std::cout << x << '\n'; return x; }
int panda(int x);
・宣言はいくつあってもよいが、定義を含む宣言は一つだけに限る。
・最初の宣言に extern "C" がなければ、C++ リンケージで、
 2番目以降の宣言に extern "C" をつけることはできない。
・最初の宣言に extern "C" があれば、C リンケージで、
 2番目以降の宣言に extern "C" をつけてもつけなくてもよい。

まだ疑問がありますか?


この投稿にコメントする

削除パスワード

No.23993

Re:他言語同士ではダメ?
投稿者---まきじ(2005/11/07 08:27:27)


>panda.c++にcリンケージを添えると、
>  panda.c++にpanda.hのインクルードと
>  panda.h  での__cplusplusマクロの真偽が不必要で。
>panda.hにcリンケージを添えると、
>  panda.c++にpanda.hのインクルードと
>  panda.h  での__cplusplusマクロが必要なのでしょうか。

extern "C" は C++ の機能だから。
C++ でコンパイルされている時だけ extern "C" を付加するため。


この投稿にコメントする

削除パスワード

No.23994

Re:他言語同士ではダメ?
投稿者---ひろし(2005/11/07 21:27:47)


すみません。
分からないのに、難しく考え過ぎていました。。。。

プログラムはコードだけでなく、ファイルという概念でも強く別れているわけなんですね。
c++の関数の実装にcリンケージ命令が無ければ、プロトタイプ宣言から呼び出して示してやるしか無いし(その際マクロ真偽が必要)。
c++の関数の実装にcリンケージ命令があれば、関数名自体がc言語規格になってしまうので、コンパイラが普通にコンパイルしてくれる。

ヘッダというモノは色々考えると不思議なファイルです。
c言語でプロトタイプ宣言する必要性を問えば、必ずしも無くてはならないファイルでもないような気がしますけど、それでも必ず必要と言う、難しいです。

凄く前進した気がします。
本当ご迷惑おかけしました。
本当にありがとうございました。


この投稿にコメントする

削除パスワード

No.23745

Re:ヘッダおよびプログラムの構造
投稿者---sakura(2005/10/20 14:14:10)


ひろしさん> ヘッダ内、プロトタイプ宣言のみされていますが、
>なぜ、プロトタイプ宣言のみで具体的に関数が動くのでしょうか。

ひろしさん
 もっと初心的な質問で申し訳ありませんが、
ヘッダファイルの内容ってどうやったら見れますか。
教えて下さい。
宜しくお願いします。
C言語歴半年ほど。


この投稿にコメントする

削除パスワード

No.23749

Re:ヘッダおよびプログラムの構造
投稿者---気分屋(2005/10/20 15:10:59)


新規の質問は必ず新しいスレッドを作りましょう。

インクルードファイルはコンパイラをインストールしたディレクトリの中の
incもしくはincludeという名前のディレクトリの中にあります。
で、関数の本体はLibディレクトリの中の、〜.libというファイルの中にあります。




この投稿にコメントする

削除パスワード

No.23755

Re:ヘッダおよびプログラムの構造
投稿者---sakura(2005/10/20 17:05:53)


>新規の質問は必ず新しいスレッドを作りましょう。
>インクルードファイルはコンパイラをインストールしたディレクトリの中のincもしくはincludeという名前のディレクトリの中にあります。

有り難う御座いました。
新規は新しいスレッドで作るように気を付けます。





この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧