• 締切済み

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ファイルも開いてみましたがよくわかりませんでした・・。 すみませんが、よろしくお願いします><

みんなの回答

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.5

★追記。 ・昔、買った本の中にC関数の実装例が載っていたものがあったので紹介します。  http://www.amazon.co.jp/dp/4774104329/→『新ANSI C言語辞典』  ただし、CD-ROM が 8 cmの小さいタイプですのでデスクトップ型パソコンでは、  本体を横置きにしないとマズイです。注意! ・今でも買えるようなのでお財布と相談して購入などをしてみてはどうでしょうか。 ・以上。わおり。

参考URL:
http://www.amazon.co.jp/dp/4774104329/
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.4

> しかしそうなるとprintfはどうやって書かれているんだ・・と思うのですが、各標準関数はどのように実装されているのかその中身を見る事はできますか? 処理系によってはソースが付いてくるかと。 VCの場合だとインストール時に選択できる場合があります。 「crt ソースコード」とかそんな感じで。 Linuxとかなら、ライブラリのソースがあるはずです。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

まず根本的なところから... #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)
回答No.2

★追記。 ・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) ); }

参考URL:
http://libc.blog47.fc2.com/blog-category-8.html
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★ちょっと違いますね。 ・stdio.h、stdlib.h、string.h のヘッダファイルには、それぞれの関数のプロトタイプ宣言などが  記述されています。このプロトタイプ宣言がないとコンパイラさんに『そんな関数はないぞ』って  叱られます。 ・strcpy 関数の場合は、ランタイムライブラリに関数の実体(内容)があります。  この関数を利用するには、使用する前にその関数のプロトタイプ宣言を記述する必要があります。  『extern char *strcpy( char *s1, const char *s2 );』という1行です。  この記述を行うとソースファイル以外の何処かに strcpy 関数の実体があるか、ライブラリにその  関数があるよ。ってコンパイラさんに教えてあげれます。するとソースファイルに strcpy 関数の  実体がなくてもライブラリや他のOBJファイルに strcpy が存在していればそれをリンカで結合して  くれます。 ・そして、標準なC関数はすべてライブラリに存在し提供されています。  これらの関数を使うには、必ずプロトタイプ宣言を記述しますが、毎回たくさんの同じ宣言を記述  するのは大変です。そこで、ヘッダファイルに処理を分類ごとに分けて記述してあります。  このことからユーザさんは(あなたも私も)ヘッダファイルをインクルードするだけで記述したことに  なるのです。 ・そもそも、プリプロセッサ命令のインクルード(#include)は、ソースファイルの位置に別のソース  ファイルを自動的に挿入する機能です。自作関数を集めたヘッダファイルをインクルードすると  インクルードされた位置に自作関数の実体を記述したのと同じ働きになります。  でも、標準にあるヘッダファイルには、関数の実体が記述されているわけではありません。注意! ・また、自作関数を集めたヘッダファイルはライブラリにして利用することをお勧めします。  そして、自作関数をライブラリにした場合もその関数群を使うにはプロトタイプ宣言が必要です。  そのプロトタイプ宣言を集めて記述したファイルこそ『ヘッダファイル』なのです。 ・決して printf 関数などがヘッダファイルに実装されているわけではありません。宣言のみです。 ・以上。分かりますか?こんな説明で。

cnyumonsha
質問者

お礼

なるほどなるほど!ありがとうございます。 私が今まで作っていたライブラリはライブラリではありませんでした・・。 ただ名前を.hにしただけのファイルでした^^; objファイルってなんなんだ?と思っていましたが、インクルードするファイルの関数があるものなんですね?? ・・ってことはobjファイルをひらけばそこに関数の内容を見ることが出来るんでしょうか? しかしそうなるとprintfはどうやって書かれているんだ・・と思うのですが、各標準関数はどのように実装されているのかその中身を見る事はできますか?

関連するQ&A

  • ptrcpy関数 コピーする領域の確保について

    prcrpyを使い、コピーする領域の確保をわざと少なめにしたプログラムを 下のようにかいたのですが、エラーが出ません。 どうしてでしょうか? #include <stdio.h> #include <string.h> main() { char s[5] = "Hello"; printf("%s\n",s); strcpy(s,"Good bye") ; printf("%s\n",s); }

  • ポインタと配列

    初歩的な質問なんですが、 #include <stdio.h> #include <string.h> main() { char ss[10]; char *p; strcpy(ss,"ABCDE"); p=ss; while(*p){ *p=*p+1; ++p; } printf("ss=%s\n",ss); } で実行結果が ss=BCDEF になります。 while(*p){ *p=*p+1; ++p; } の部分がどうしても理解できません。 参考書にも、解説が載ってなくて困っています。 ご教授宜しくお願いします。

  • 配列について

    初歩的な質問ですいませんが、質問よろしくお願いします。 ◎1----------------------------- #include<stdio.h> int main(void) { char ss[10]="AB"; printf("ss=%s\n",ss); return 0; } ------------------------------------ ◎2-------------------------------- #include<stdio.h> int main(void) { char ss[10]; ss[0]='A'; ss[1]='B'; ss[2]=0; printf("ss=%s\n",ss); return 0; } ----------------------------------- ◎3------------------------------- #include<stdio.h> #include<string.h> int main(void) { char ss[10]; strcpy(ss,"AB"); printf("ss=%s\n",ss); return 0; } ----------------------------------- ◎4------------------------------- #include<stdio.h> int main(void) { char ss[10]; ss="AB"; printf("ss=%s\n",ss); return 0; } ---------------------------------- 以上4つのプログラムで、◎2と◎3は正常に動くと理解できたのですが、何故、◎1は正常に動き、◎4は「'const char [3]' から 'char [10]' に変換できません。」といったようなエラーが出てしまうか分かりません。 教えていただければ嬉しいです。

  • 構造体の型について

    ある構造体をxxxと名づける以下のプログラムを作成しました。 ーーーーーーーーーーー #include <stdio.h> #include <string.h> main() { typedef struct { char variable[64]; char type[64]; char value[512]; } xxx; xxx aaa; strcpy(aaa.variable,"bbb"); printf("%s\n",aaa.variable); } ーーーーーーーーーーー これは動き、bbbと表示されます。 しかしながら、構造体のポインタを使用した 以下のプログラムではコンパイルはとおりますが実行時にコアダンプして落ち ます。 ーーーーーーーーーーーーーーーーーーーー #include <stdio.h> #include <string.h> main() { typedef struct { char variable[64]; char type[64]; char value[512]; } xxx; xxx* aaa; strcpy(aaa->variable,"bbb"); printf("%s\n",aaa->variable); } ーーーーーーーーーーーーーーーーーーーーーーー 両プログラムの意図はまったく同じなのに何故いけないのでしょうか。

  • char型ポインタ

    よくプログラムで charポインタだけ指定して、 #include<stdio.h> int main(){ char* p; p = "abcdef"; printf("%s",p); return 0; } のようにしているのをみかけますが、 メモリーを確保していなくても問題ないのでしょうか? char* p; p = (char*)malloc(7); strcpy(p,"abcdef"); としたのと同じでしょうか?

  • strncpy後のatoiがおかしい

    こんにちは。 C++をVS2005でやっています。 atoi関数を使っているんですが、10個の配列strにstrncpyをやると値がおかしくなります。 10個目に'\0'を代入させてやってみても駄目でした。 以下にソースを載せます。 #include <string.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> int main( void ) { char string[256]; char str[10]; char *moji = "12345464"; int l; // using template versions of strcpy_s and strcat_s: strcpy(string, "6877897898"); strcat(string, "strcpy_s"); strcat(string, "and"); // of course we can supply the size explicitly if we want to: strcat(string, "strcat_s!"); strncpy(str, string, 10); l = strtol(str,NULL,10);// 値が違う 6877897898にならない printf("str = %d\n", l); l = atoi(moji); printf("moji = %d\n", l); l = atoi(string);// 値が違う printf("string = %d\n", l); printf("String = %s\n", string); getchar(); return 0; } 表示結果 str = 2147483647 moji = 12345464 string = 2147483647 String = 6877897898 mojiは正常に動作しますから、ナル文字が原因なのかと思ってしまいますが。原因がいまいち分かりません。 よろしくお願いします。

  • CSVを用いた検索プログラム動かし方

    #pragma warning( disable: 4996 ) #include <stdio.h> #include <string.h> #include <fstream> using namespace std; typedef struct tagKOTOWAZA{ char japanese[50]; char english[50]; }KOTOWAZA; int main() { char buf[256]; KOTOWAZA c[200]; int i, count; /*ifstream strtok strcpy を使ってファイルを読み込む*/ //=====ここから===== ifstream fin("Book1.csv"); if(fin.is_open()){ //ファイル内容の表示とクローズ for(count=0;fin.getline(buf, sizeof(buf)), !fin.eof();count++){//読み込める間 //printf("%s",buf);デバッグ用 char *p; p = strtok(buf,","); if(p)strcpy(c[count].japanese,p); p = strtok(NULL,","); if(p)strcpy(c[count].english,p); } fin.close(); }else{ printf("ファイルのオープンに失敗しました。\n"); return 1; } //=====ここまで==== return 0; } ここからどうすればCSVファイルに書いた 漢字,English を検索できるのかがわかりません・・・ 言語はC++を使っていますvisualstudio2012を使っています。 どうすればいいのか全く分かりません。 よろしくお願いします。

  • 構造体宣言したポインタ変数に値を代入するには?

    strcpy(p -> key ,name);と打ってp -> key に入力した名前を格納したいのですがうまくいきません。 ほかにもp -> key = nameなども試してみましたがコンパイルエラーが出現してダメでした。 うまく格納できるやり方があれば教えてください。よろしくお願いします。 #include<stdio.h> #include<string.h> #define WORD_LENGTH 50 /* 文字列の最大長 */ typedef struct cell{ char key[WORD_LENGTH]; struct cell *next; /* 次のセルへのポインタ */ } CELL; void main(void) { char name[WORD_LENGTH]; CELL *p; printf("名前入力\n"); scanf("%s\n", name); strcpy(p -> key ,name); printf("%s\n", p -> key); }

  • 文字列のコピー

    C言語で、文字列をコピーする関数で、処理が止まってしまいます。 以下が実行したプログラムです。 #include<stdio.h> #include<string.h> void copy(char *str2 ,char *str3){ strcpy(str2,str3); } void input(char* str){ scanf("%s",str); } int main (void){ char *a; char *b="TEST"; printf("%s\n",b); input(a); copy(b,a); printf("%s",b); return(0);} copy(b,a);で処理が止まってしまいます。入力した文字列を表示できるように、御指摘お願いします。

  • 乱数を使って

    プログラム #include<stdio.h> #include<string.h> #include<stdlib.h> main() { char land[10][10]; int i, j; for(i=0; i<10; i++) { for(j=0; j<10; j++) { strcpy( &land[i][j], "□"); printf("%s",&land[i][j]); } printf("\n"); } } で発生させた10×10の□の上に、 乱数を使って■を25個上書きしたいのですが、 どうしたらできるか教えてください。

専門家に質問してみよう