- 締切済み
string.h とかって何?
#include で最初に含むファイルっていったい何者なんでしょうか? rand()を使うにはstdlib.hをインクルードしますし、printfのような入出力関係にはstdio.hを、文字関係ならstring.hを・・。 それはわかるのですが、これは、それぞれのヘッダファイルに自作関数の集合のようなものが入っていると考えるのは間違いなんでしょうか? 例えば、strcpyを使用するにはstring.hをインクルードするべきですが、 それはstring.hの中に char *strcpy(char *s1, const char *s2) { char *p = s1; while (*s1++ = *s2++) ; return (p); } みたいな記述が入っていると想像するのは間違いですか? 自作関数を集めてヘッダファイルにする事出来ますけど、これらは違うんですか? これだとprintfとかどうやって実装しているんだって思ってしまって・・。 直接stdio.hを開いてみたものの意味不明で、其の中にさらにある.hファイルも開いてみましたがよくわかりませんでした・・。 すみませんが、よろしくお願いします><
- みんなの回答 (5)
- 専門家の回答
みんなの回答
- Oh-Orange
- ベストアンサー率63% (854/1345)
★追記。 ・昔、買った本の中にC関数の実装例が載っていたものがあったので紹介します。 http://www.amazon.co.jp/dp/4774104329/→『新ANSI C言語辞典』 ただし、CD-ROM が 8 cmの小さいタイプですのでデスクトップ型パソコンでは、 本体を横置きにしないとマズイです。注意! ・今でも買えるようなのでお財布と相談して購入などをしてみてはどうでしょうか。 ・以上。わおり。
- Wr5
- ベストアンサー率53% (2173/4061)
> しかしそうなるとprintfはどうやって書かれているんだ・・と思うのですが、各標準関数はどのように実装されているのかその中身を見る事はできますか? 処理系によってはソースが付いてくるかと。 VCの場合だとインストール時に選択できる場合があります。 「crt ソースコード」とかそんな感じで。 Linuxとかなら、ライブラリのソースがあるはずです。
- jacta
- ベストアンサー率26% (845/3158)
まず根本的なところから... #includeの後に指定するヘッダ名が、"..."の形式か<...>の形式かによって意味が異なります。"..."の場合は、その名前のソースファイルを探索し、見つかった場合はそのファイルを取り込みますが、見つからなければ<...>と同じように振る舞います。<...>は処理系の標準ヘッダを取り込みます。標準ヘッダはファイルとは限りません。ただし、大多数の処理系の場合はファイルですので、一度そのファイルをじっくり調べてみることをお勧めします。 ヘッダ(またはヘッダファイル)の中には、通常、型やマクロの定義および外部変数や関数の宣言が含まれていますが、場合によっては関数の定義が含まれていることもあります。具体的にはインライン関数であったり、C++の場合は関数テンプレートであったりするわけです。 > これだとprintfとかどうやって実装しているんだって思ってしまって・・。 printfの場合、stdio.hの中には、 int printf(const char*, ...); という関数の宣言があるだけです。 関数の実体は、 #include <stdio.h> #include <stdarg.h> int printf(const char *format, ...) { va_list ap; int count; va_start(ap, format); coount = vfprintf(stdout, format, ap); va_end(ap); return count; } のようになっています。(vfprintfの代わりにvprintfかもしれませんが...) #2の回答のように、vsprintfを使うと出力文字数に制約ができるため、printfの仕様を満たすことができません。 この関数は、通常、あらかじめコンパイルされてバイナリ形式で処理系が持っており、リンク時にくっつけられます。 Cの場合、上のprintfと同じように、外部で関数の実体が定義された上で、ヘッダ内でマクロとして別途定義される場合があります。例えば、abs関数のような単純なものの場合、 int abs(int j) { return j < 0 ? -j : j; } という外部定義の他に、 int abs(int); #define abs(j) ((j) < 0 ? -(j) : (j)) というマクロをヘッダ内で行っても良いことになっています。 この場合、ヘッダをインクルードすればマクロが、ヘッダなしで呼び出せば外部定義の関数が呼び出されることになります。ヘッダをインクルードした場合でも、引数なしでabsだけを(すなわち関数へのポインタとして)使った場合は外部関数が使われますし、明示的に(abs)(123)のように関数名を括弧でくくれば、マクロではなく外部関数を呼び出すことができます。
- Oh-Orange
- ベストアンサー率63% (854/1345)
★追記。 ・objファイルはバイナリファイルですので、普通に開いても関数の内容は見れません。 でも関数をコンパイルして機械語(アセンブラ)レベルで関数の処理内容が分かります。 逆アセンブルなどすれば分かるかも。→その前に obj ファイルの構造を解読しないと いけませんね。 ・標準関数のソースが処理系に付属していれば見れます。 でも自分で実装してみるとよりC言語の仕組みを理解できます。→自分でも実装できる。 過去に『ライブラリのソースを見る方法はないでしょうか?』という質問がありました。 http://oshiete1.goo.ne.jp/qa2856744.html→『C言語のライブラリ』をどうぞ。 ・下に printf 関数だけですが実装例を載せます。 #include <stdio.h> #include <stdarg.h> // 標準関数の printf 関数と等価です。 extern int printf( const char format[], ... ) { char buff[ 1024 ]; va_list ap; va_start( ap, format ); vsprintf( buff, format, ap ); va_end( ap ); return( fputs(buff,stdout) ); }
- Oh-Orange
- ベストアンサー率63% (854/1345)
★ちょっと違いますね。 ・stdio.h、stdlib.h、string.h のヘッダファイルには、それぞれの関数のプロトタイプ宣言などが 記述されています。このプロトタイプ宣言がないとコンパイラさんに『そんな関数はないぞ』って 叱られます。 ・strcpy 関数の場合は、ランタイムライブラリに関数の実体(内容)があります。 この関数を利用するには、使用する前にその関数のプロトタイプ宣言を記述する必要があります。 『extern char *strcpy( char *s1, const char *s2 );』という1行です。 この記述を行うとソースファイル以外の何処かに strcpy 関数の実体があるか、ライブラリにその 関数があるよ。ってコンパイラさんに教えてあげれます。するとソースファイルに strcpy 関数の 実体がなくてもライブラリや他のOBJファイルに strcpy が存在していればそれをリンカで結合して くれます。 ・そして、標準なC関数はすべてライブラリに存在し提供されています。 これらの関数を使うには、必ずプロトタイプ宣言を記述しますが、毎回たくさんの同じ宣言を記述 するのは大変です。そこで、ヘッダファイルに処理を分類ごとに分けて記述してあります。 このことからユーザさんは(あなたも私も)ヘッダファイルをインクルードするだけで記述したことに なるのです。 ・そもそも、プリプロセッサ命令のインクルード(#include)は、ソースファイルの位置に別のソース ファイルを自動的に挿入する機能です。自作関数を集めたヘッダファイルをインクルードすると インクルードされた位置に自作関数の実体を記述したのと同じ働きになります。 でも、標準にあるヘッダファイルには、関数の実体が記述されているわけではありません。注意! ・また、自作関数を集めたヘッダファイルはライブラリにして利用することをお勧めします。 そして、自作関数をライブラリにした場合もその関数群を使うにはプロトタイプ宣言が必要です。 そのプロトタイプ宣言を集めて記述したファイルこそ『ヘッダファイル』なのです。 ・決して printf 関数などがヘッダファイルに実装されているわけではありません。宣言のみです。 ・以上。分かりますか?こんな説明で。
お礼
なるほどなるほど!ありがとうございます。 私が今まで作っていたライブラリはライブラリではありませんでした・・。 ただ名前を.hにしただけのファイルでした^^; objファイルってなんなんだ?と思っていましたが、インクルードするファイルの関数があるものなんですね?? ・・ってことはobjファイルをひらけばそこに関数の内容を見ることが出来るんでしょうか? しかしそうなるとprintfはどうやって書かれているんだ・・と思うのですが、各標準関数はどのように実装されているのかその中身を見る事はできますか?