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

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

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

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

Q&A

2回答

2165閲覧

ストーリム入出力について c

reotantan

総合スコア295

C

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

0グッド

0クリップ

投稿2015/09/06 15:37

ストリーム入出力では,文字単位や行単位でファイルを読み書きする関数が直接ファイルをアクセスするのではなく,OSが設定したバッファ*1にアクセスして,バッファとの間で読み書きを行います。つまり,ストリーム入出力はバッファを使った入出力です。

バッファの内容がすべて読み込まれ,バッファが空になったときは,OSが自動的にファイルの内容を読み込んでくれます。同様に書き込みによってバッファいっぱいになったときには,OSが自動的にファイルへ書き込んでくれます。このストリーム(流れ)により,プログラム側では1文字ずつ読み書きする処理であっても,ファイルへのアクセスが効率的に行われるわけです。

例えば打った文字や数字は一旦バッファ(あるメモリ領域)に保存されて、必要になったらバッファから取り出すという事ですか?ただし、バッファがいっぱいになったらOSが自動的にファイルへ書きこむとはどういう事でしょうか?

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

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

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

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

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

guest

回答2

0

ごく一般的な理解という意味では、reotantanさんのご理解は間違っていないですが、厳密に言えば、C言語のストリームという言葉は、いわゆるバッファリングとは無関係の概念を表しています。

詳しくは こちら をご覧頂ければと思いますが、ストリームとは、プログラムが文字を読み書きする対象すべてを一元的に扱うためのインターフェイスであり、抽象的な概念に過ぎません。
ファイルもキーボードもコンソールのディスプレイも、すべてがストリームです。

これはちょうど、Unix系のOSで、入出力の対象となるあらゆるデバイスを**仮想ファイルシステム(VFS)**という抽象化された管理機構によって一元的に管理しているのと同じです。(参照)

OSのファイルシステムの場合、具体的な実装として、ext4 や Btrfs、NFS などを使用目的に合わせて選択しますが、それぞれのファイルシステムは独自のバッファリング機構を持っています。

C言語のストリームも同様で、

バッファリングしないと、ストリームに対し、文字を一字づつ読み込みまたは書き込みます。バッファリングすると、書き込みに対しては、文字を受け取り、バッファが満杯になると書き込みます。読み込みに対しては、文字を渡し、バッファが空になると、満たします。

が、これらは使用目的に応じてプログラマーが選択します。

( getchar や putchar ) 誤記訂正→ readwriteのように、ストリームに対するアクセスを、OSのシステムコールを直接呼び出すことで実現した関数は「低水準入出力関数」と呼ばれますが、これがいわゆるバッファリングなしです。
この場合、ストリームの に滞留する文字は無いため、通常はストリームの存在を意識する事はあまりなく教科書の説明にも登場しないです。

一方、getsputsなどの「高水準入出力関数」は、「ファイル構造体 (FILE) 」というデータを介してファイルにアクセスします。このファイル構造体は、いわゆるバッファ(=メモリー上に確保された領域)をソフトウェア的に表現したものであり、構造体をどのように定義するかによってバッファリング動作が決まります。(詳細はこちらを参照)

つまり、高水準入出力関数を使用する場合は自動的にバッファリングされる事になり、しかも教科書ではバッファリング動作の説明のためにストリームという用語を何度も繰り返すので、「ストリーム=バッファリングあり」と誤解されているのだと思います。

さらに言えば、このバッファは、ファイル構造体という形でC言語処理系が用意するものであり、OSの動作とは無関係です。
一方、OSの方は、プログラム(C言語処理系)の側がバッファリングするかどうかに関わりなく、ファイルシステムとしてのバッファリングを行うのが普通です。

ですから、以下のご質問

例えば打った文字や数字は一旦バッファ(あるメモリ領域)に保存されて、必要になったらバッファから取り出すという事ですか?ただし、バッファがいっぱいになったらOSが自動的にファイルへ書きこむとはどういう事でしょうか?

の直接の回答としては、

  • 「低水準入出力関数」を使用した場合は、OSのVFSとの間で即時に文字のやりとりが実施される
  • 「高水準入出力関数」を使用した場合は、バッファ(=ファイル構造体)の単位でOSのVFSとやりとりされる

ただし、実際にファイルに 物理的に(HDDに) 書き込まれるのは、OSのVFS側でバッファが一杯になったタイミングです。
とは言え、プログラムからはVFSしか見えない(OSのバッファリング動作は隠蔽されている)ので、バッファリングあり(高水準入出力関数を使用)の場合でも、ファイル構造体の中身だけを意識していれば良い、ということになります。

次に、

このストリーム(流れ)により,プログラム側では1文字ずつ読み書きする処理であっても,ファイルへのアクセスが効率的に行われるわけです。

という点についてですが、この効率的かどうかについても、やはり目的次第です。

通常のアプリケーションプログラムの場合、いわゆる文章を行単位に処理する事が多く、その場合にはバッファリングを行いつつレコード番号によってアクセスできた方が速いし楽です。
しかし、リアルタイムOSや、いわゆる組み込み系ソフトのようにクリティカルな処理の求められる場合には、勝手にバッファリングされると困る場合もあります。
一見、不便で出番の少ない「低水準入出力関数」がいつまでも無くならない理由は、そういうところにもあると思います。

以上、かなり細かくなってしまいましたが、ご参考になれば幸いです。

投稿2015/09/07 21:58

編集2015/09/08 13:15
pi-chan

総合スコア5936

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

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

otn

2015/09/08 13:03

低水準入出力は、read/writeです。getchar/putcharは高水準入出力ですよ。 FILE構造体を使った物がストリーム入出力(高水準入出力)で、バッファリングするかどうかはsetbuf関数などで指定できるので、「ストリーム」=「バッファリングする」ではないのは仰る通り。
pi-chan

2015/09/08 13:16

大変失礼致しました。。。誤りを訂正しておきました。
otn

2015/09/08 13:30

あれ?読み誤ったかもしれません。ファイルディスクリプタとストリーム(FILE構造体)をごっちゃに論じてませんか?
guest

0

最初の二段落はどこかからのコピペ転載で、最後の段落が質問ということでしょうか?

打った文字や数字は一旦バッファ(あるメモリ領域)に保存されて、必要になったらバッファから取り出という事ですか?

「打った」というのが入力なのか出力なのか不明ですが、おおむね、そういう感じです。

バッファがいっぱいになったらOSが自動的にファイルへ書きこむとはどういう事でしょうか?

どのあたりがわからないのでしょうか?バッファの概念が分からない?
ストリームで無い入出力(read/write)については理解されてますか?

投稿2015/09/06 15:59

otn

総合スコア84421

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

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

reotantan

2015/09/06 21:38

バッファの概念は本で見たのですが、あまり詳しく書いてありませんでした。 ストーリムでない入出力は理解していないと思います。 説明していただけると嬉しいです。
otn

2015/09/07 14:37

ストリームで無いダイレクトな入出力は、プログラムから入出力関数(read/write)を呼び出すとその時点でOSに対して入出力要求が行われます。 ストリーム入出力では、設定次第ですが、普通は「バッファ」という作業エリアを使って、ライブラリがプログラムからの入出力関数呼び出しをいくつかまとめて、OSに入出力要求を行います。 たとえて言うと、 ・ゴミが出る度に、ゴミ捨て場に運ぶ⇒バッファを使わない出力 ・ゴミが出たらゴミ箱に捨て、ゴミ箱がいっぱいになったらゴミ捨て場に運ぶ⇒バッファを使った出力
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問