feof関数について調べると、
・ストリームがファイルの終端かどうか調べる。
・終端指定子がセットされているかどうか調べる。
と、サイトによって説明のしかたが2つに分かれていました。
不思議に思ってstdio.hを調べてみると、

 #define _IOEOF 0x0010
 #define feof(_stream) ((_stream)->_flag & _IOEOF)

こんな感じになっていました。
上だとエラー指示子と0x0010(10進数で16)の論理積を出しているようですが、0x0010が何を意味するのかがわからないのでなにがなんだかです。
feofはどういう関数なのでしょうか?
回答よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

<stdio.h>の実装については#1さんの通りです。



feofはthe end-of-file indicatorがセットされているかどうかを調べる関数です。
# 規格 (ISO/IEC 9899:1999) 7.19.10.2 The feof function

まず,規格7.19.3 Filesの11段落に,
> The byte input functions read characters from the stream as if by successive calls to the fgetc function.
とありますので,<wchar.h>で定義されるワイド入出力関数を除くと,ファイルの読み込みはすべてfgetcを使った読み込みを経由していると見なせます。
次に規格7.19.7.1 The fgetc functionの第3段落には
> If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returns EOF.
とあります。つまり,
・ストリームが終端に達した後,さらに読み込もうとするとthe end-of-file indicatorがセットされる
ということになります。

なので,
> ・ストリームがファイルの終端かどうか調べる。
ではなく,
> ・終端指定子がセットされているかどうか調べる。
が正しいことになります。
前者は曖昧と言えば曖昧ですが,終端に達した後「さらに読み込もうとした」ことが必要なので。
    • good
    • 0
この回答へのお礼

わかりました!
回答ありがとうございました。

お礼日時:2009/05/14 20:55

feof関数は、「ファイル終了表示子」がセットされているかどうかを判定します。



fgetcやfread等のストリーム入力関数によって値を読み込んだ結果、ファイルの終端に達しても、その時点ではファイル終了表示子はセットされません。その状態でさらに読み込もうとした時点でファイル終了表示がセットされます。

また、いったんファイル終了表示子がセットされたとしても、clearerrの呼び出し等によって、ファイル位置表示子がファイルの終端にあるままの状態でファイル終端表示子はクリアされ、feofが0を返すようになります。
    • good
    • 0
この回答へのお礼

回答ありがとうございました!

お礼日時:2009/05/14 20:56

FILE構造体の仕様がコンパイラによってまったく違うので_IOEOFの意味を考えても意味がないです


調べられたコンパイラではFILE構造体のメンバ変数であるflagの下から5ビット目が終端指定子なのでしょう
ファイルの終端にきたら終端指定子がセットされるので
feofはストリームがファイルの終端かどうかを(終端指定子がセットされているかどうかで)調べる関数になります。
    • good
    • 0
この回答へのお礼

回答ありがとうございました!

お礼日時:2009/05/14 20:48

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC言語 コンパイラ

C言語のコンパイラを無料でインストールしたいのですが
気に入ったのが見つかりませんでしたぁ
いいコンパイラがあったら教えてください
よろしく御願いします

Aベストアンサー

その前に対象OSやプラットフォームなどの環境を書かないと何とも
いえないと思います。

クロスコンパイラならみなさんのいうようにGCCが一番でしょうし、
Winに限定するならBCCかVC++ Express Editionがいいでしょう。
MS-DOSならLSI C-86試食版なんてのもありますけど。

なんか、上手く動作しないけどWatcom Cなんて手もあるかも。

Cだけでいいのか、C++が使えた方がいいのかによっても異なります。

参考URL:http://ja.wikipedia.org/wiki/C%E8%A8%80%E8%AA%9E

Q#define __T(x) L ## x について

tchar.hにある

#define __T(x) L ## x

の xは使われていない?のですが、どう解釈すればよいのでしょうか?

また、__T(_が2つ)は _TやTEXTマクロのことでしょうか?

Aベストアンサー

もし、

#define __T(x) L ## x



#define __T(x) Lx

と書いてしまっては、__T(x)はいつもLxと解釈されてしまいます。
## は連結だと思ってください。

#define __T(x) L ## x

とすることで x は引数の x であることを示しています。

QC言語のコンパイラについて

私は、高校でC言語を使った授業をしています。
学校のPCではMinGWのコンパイラを使っています。
家のPCでもC言語をしたいのですがコンパイラの入手法がわかりません。
どなたか教えてください。

Aベストアンサー

あなたの自宅のPCがwindowsであるならば、Cygwinを使われたらどうでしょう?
mingwのCコンパイラも存在します。

参考URL:http://cygwin.com/

Q#define NULL ((void *)0) の弊害

よく話題にされるヌルポインタについての疑問です。

定数の0は、それがポインタと解されるべき文脈では
ヌルポインタに読み替えられますが、
可変長引数のようにポインタであることがコンパイラには判断できない文脈では、
明示的にキャストしてやらなければなりません。
このとき、#define NULL 0 と定義されている処理系では、
NULLを使っても定数の0を書いたのと全く同じであり、
上のような場合におけるキャストの必要性からは逃れられません。
しかし、たまたま自分の処理系で
#define NULL ((void *)0) と定義されていれば、
キャストを行わなくてもNULLを使うことによって正しく動いてしまいます。
ということは、#define NULL ((void *)0) と定義された処理系しか
使ったことの無いプログラマは、
「NULLを使うこと自体が、これはポインタだよという意志表示になる」
と錯覚してしまう危険性をはらんでいることになります。
この人の書いた「NULLを使い、必要なキャストを省略しているソース」を、
#define NULL 0 と定義された処理系でコンパイルすると
正しく動作しない可能性があります。

こういう弊害があるにもかかわらず、
ANSI Cでは #define NULL 0 のほかに
#define NULL ((void *)0) も許しているのは、
一体なぜなのでしょうか。
メリットもあるのでしょうか?

よく話題にされるヌルポインタについての疑問です。

定数の0は、それがポインタと解されるべき文脈では
ヌルポインタに読み替えられますが、
可変長引数のようにポインタであることがコンパイラには判断できない文脈では、
明示的にキャストしてやらなければなりません。
このとき、#define NULL 0 と定義されている処理系では、
NULLを使っても定数の0を書いたのと全く同じであり、
上のような場合におけるキャストの必要性からは逃れられません。
しかし、たまたま自分の処理系で
#define NULL ((voi...続きを読む

Aベストアンサー

(1)
> ポインタと数値との内部構造の共通性から
> 結果として正しく動く、という意味でよろしいでしょうか?
その解釈でよいと思います。
私は「NULLは0または0Lと同一構造をもつ無効ポインタ」という解釈で使っています。

(2)
> すなわちNULLをキャスト無しで用いて大丈夫な場合が無くなってしまうのでしょうか?
例えばintel16bit系ではコンパイラが「デフォルトポインタ構造」を提供します。
メモリモデルと呼ばれるもので、コンパイルオプションによって16bitポインタと32bitポインタが指定可能です。
デフォルトポインタ構造を持つ無効ポインタをNULLと表現することは可能になります。
しかし、コンパイルオプションで16bitポインタを指定している場合でも、32bitポインタが必要なことがあり、この場合は適切なキャストが必要です。
他の処理系でも同様な措置によって「多くの場合はNULLが利用可能」と言うことになるでしょう。
しかし、「デフォルトのポインタ構造が可変」という状況はポータビリティーを阻害する可能性があることは間違いありません。

(1)
> ポインタと数値との内部構造の共通性から
> 結果として正しく動く、という意味でよろしいでしょうか?
その解釈でよいと思います。
私は「NULLは0または0Lと同一構造をもつ無効ポインタ」という解釈で使っています。

(2)
> すなわちNULLをキャスト無しで用いて大丈夫な場合が無くなってしまうのでしょうか?
例えばintel16bit系ではコンパイラが「デフォルトポインタ構造」を提供します。
メモリモデルと呼ばれるもので、コンパイルオプションによって16bitポインタと32bitポインタが指定可能で...続きを読む

QC言語でのコンパイラの作成方法

C言語初心者のため、稚拙な文章になる可能性があることを最初にお詫びします。

現在Microsoft社のMicrosoft Visual C++ 6.0を用いてCドライブのルートにある「temp.c」というソースファイルをコンパイルするアプリケーションを作ろうと思っているのですが、ネット上で「C言語 コンパイラ 作成」等と検索しても、既にコンパイラがあることを前提としたホームページしか見つけることができず、肝心のコンパイラをどのように作ったらよいのかということが載ったホームページが見つかりません。

というわけで、今回はコンパイラをどのように作ったらよいのかというヒントだけでもいいので教えて頂けないかと思い投稿させて頂きました。
ちなみに「temp.c」はそこまで複雑なソースではなく、DOS上のアプリで、リソースやアイコンなどは用いないものです。


そもそも「コンパイラを作る」ということ自体が愚かな行為なのかと思ったりもします。
私が所持しているBcpadやMicrosoft Visual C++ 6.0に付属している既存のコンパイラを利用するということも考えたのですが、BcpadやMicrosoft Visual C++ 6.0の本体以外からコンパイラをどのように利用していいのかもわかりません。

どうぞ忌憚の無い意見をよろしくお願いします。
ちなみにOSはXPのSP3です。

C言語初心者のため、稚拙な文章になる可能性があることを最初にお詫びします。

現在Microsoft社のMicrosoft Visual C++ 6.0を用いてCドライブのルートにある「temp.c」というソースファイルをコンパイルするアプリケーションを作ろうと思っているのですが、ネット上で「C言語 コンパイラ 作成」等と検索しても、既にコンパイラがあることを前提としたホームページしか見つけることができず、肝心のコンパイラをどのように作ったらよいのかということが載ったホームページが見つかりません。

というわけで、...続きを読む

Aベストアンサー

あの・・・水を差すようで恐縮しますが

それって「コンパイラを作る」ではなくて
「コンパイラを呼び出す」だけでは?

ボタンを押したら
外部プログラムとして cc コマンドを実行するだけ…。
最近 C++ やってないんで忘れましたが WinExecとか CreateProcess とか使って…。もちろん環境変数や実行パラメータはきちんとセットした上でですけど…。Microsoft Visual C++ 6.0でもコマンドプロンプトだけでコンパイルできますから。

Q【#define】 defineで定義した値を配列のサイズに使う事は可能?

タイトルの通り、defineで定義した値を配列のサイズ指定に使いたいと考えています。
この場合、次のような使い方をしても問題ないのでしょうか?

/* サンプルここから */
#define SIZE_A 10
#define SIZE_B 20
#define SIZE_ALL (SIZE_A * SIZE_B)

cahr ARR[SIZE_ALL];
/* サンプルここまで */

コンパイル時にワーニング等はありませんが、int型という型を宣言していないSIZE_ALLを要素数として使用するのが不安に感じるのですが問題ないのでしょうか?

int SIZE_int = SIZE_ALL;
とdefineした値を明示的にint型変数に代入した上で、
cahr ARR[SIZE_int];
とすべきなのでしょうか?

初歩的な質問ですが、ご教示お願いします。

Aベストアンサー

★特に問題ありません。
・普通に define された定数を掛け算などして新しい記号定数を定義します。
 そしてその記号定数を配列などの添え字に使います。
 そもそも define された定数は通常は int 型と同じになります。
 #define SIZE_A 10…int型
 #define SIZE_A 10L…long型
 #define SIZE_A 10LL…long long型
 となります。
 『L』や『LL』のサフィックスを付けないとすべて int 型に解釈されます。
 つまり、プリプロセッサ命令は単純な文字列の置換ですのでサフィックスを
 付けないと int 型になるわけですよ。
・もし char 型にしたいならキャストを指定します。
 例えば
 #define SIZE_A ((char)(10))
 とします。
・もう既に回答がありますが
>int SIZE_int = SIZE_ALL;
>とdefineした値を明示的にint型変数に代入した上で、
>cahr ARR[SIZE_int];
>とすべきなのでしょうか?
 ↑
 この方法は新しい記述方法です。
 1999年の最新のC言語の規格です。
 この C99 にすべてのコンパイラが対応しているわけではないため使わない方が
 良いかもしれません。この記述が利用できれば便利なこともありますが…。
・最後にカッコをつけた方が良いですよ。
 #define SIZE_A (10)
 #define SIZE_B (20)
 #define SIZE_ALL (SIZE_A * SIZE_B)
 という風に SIZE_A、SIZE_B に括弧を付けます。
 これは今後 SIZE_A を『10 + 20』と定義した際に括弧がないと計算式が
 正しくなくなるので付けるように習慣を付けておいた方が良いということです。
 つまり今後
 #define SIZE_A 10 + 20
 #define SIZE_B 20 * 3
 #define SIZE_ALL (SIZE_A * SIZE_B)
 と定義したとします。
 すると SIZE_ALL は (10 + 20 * 20 * 3) と置換されますが計算式が掛け算を先に
 する数学上のルールより意図しない結果になります。正しくは SIZE_ALL=1800 に
 なるべくところが SIZE_ALL=1210 となってしまいます。
・これを防ぐには2つ。
 #define SIZE_A (10 + 20)
 #define SIZE_B (20 * 3)
 #define SIZE_ALL (SIZE_A * SIZE_B)
 もしくは
 #define SIZE_A 10 + 20
 #define SIZE_B 20 * 3
 #define SIZE_ALL ((SIZE_A) * (SIZE_B))
 と定義します。
 どちらにカッコを付けても同じですが私はすべてにカッコを付ける派です。
・参考にして下さい。

★特に問題ありません。
・普通に define された定数を掛け算などして新しい記号定数を定義します。
 そしてその記号定数を配列などの添え字に使います。
 そもそも define された定数は通常は int 型と同じになります。
 #define SIZE_A 10…int型
 #define SIZE_A 10L…long型
 #define SIZE_A 10LL…long long型
 となります。
 『L』や『LL』のサフィックスを付けないとすべて int 型に解釈されます。
 つまり、プリプロセッサ命令は単純な文字列の置換ですのでサフィックスを
 付けないと ...続きを読む

QC言語のコンパイラ

C言語の勉強がしたいと思っているのですが、コンパイラっていうんですかね、それについて少し調べてみたら
無料なら"Borland C++ Compiler"で、有料ならなんかかなり高いっぽいけど"Visual C++"っていうのがあることが解りました。

よくプログラミング系のサイトの人で"Borland C++"のコンパイラを利用してとてもプログラミングがしやすくなったということが書いてあるのですが、"Visual C++"と比べたらどっちの方がいいんですか?(やっぱり有料の方?)
もし人それぞれなら、みなさんは両方あったらどっちを使いますか?

初心者なら無料ので十分すぎるのだとは思いますが、プログラマーみたいな人から見るとどうなのかな~と思ったので教えていただけますか。
お願いします。
ついでに"Visual C++"って言語があるんですかね?何かそんな風に書いてあるところもあったもんで。
かさねがさねお願いします。

Aベストアンサー

Borland C++ Compilerは元々は有料ですよ。(パッケージ販売していた。)

統合環境など(IDE)を省いて無料として公開したものなのでなんら、無料だからといって劣る部分はありません。
(コンパイル速度もBC++の方が速いし。)

VC++がいいと言われている利点はMS社製なのでOSと同じ会社と言うことで親和性が高い、サンプルソースコード等の資料がボーランド用に比べて極端に多いという利点があります。

勿論、VC++用のソースコードでもBC++とVC++の違いを理解していれば、コンパイル可能です。(ライブラリ関係の呼び出し方が違うのでDLLをBC++用にインポートするなど)

個人的な意見ですが、純粋にプログラムを学びたいというのであればBC++で十分です。(もったいないくらい、昔は5,6万位だして買った記憶が、、、。)

本格的にWindowsのプログラムを学びたいのならVC++の購入を検討してみるべきです。(逆に、それくらいの金額を自分に投資できないならたとえVC++が無料であっても使いこなさないと思います。)

Borland C++ Compilerは元々は有料ですよ。(パッケージ販売していた。)

統合環境など(IDE)を省いて無料として公開したものなのでなんら、無料だからといって劣る部分はありません。
(コンパイル速度もBC++の方が速いし。)

VC++がいいと言われている利点はMS社製なのでOSと同じ会社と言うことで親和性が高い、サンプルソースコード等の資料がボーランド用に比べて極端に多いという利点があります。

勿論、VC++用のソースコードでもBC++とVC++の違いを理解していれば、コンパイル可能です。(ライブ...続きを読む

QC言語のプログラムで#includeを使わず#includeだけで

C言語のプログラムで#include<math.h>を使わず#include<stdio.h>だけで√(sqrt)を表現することは可能でしょうか?

Aベストアンサー

ご自分で sqrt 関数を作れば可能です。
こんな感じでしょうか。

#include <stdio.h>

static double
sqrt (double s)
{
 double x = s / 2.0;
 double last_x = 0.0;

 while (x != last_x)
 {
  last_x = x;
  x = (x + s / x) / 2.0;
 }

 return (x);
}

int
main (int argc, char * argv[])
{
 printf ("sqrt (%f) = %f\n", 3.0, sqrt (3.0));
}

QMacで使えるC言語のコンパイラを教えてください

最近C言語の勉強を始めました。
私はMacユーザなのですがMacでCを使えるコンパイラはあるのでしょうか。ネットで探しても見つかりませんでした。もしご存じでしたら教えてください。

Aベストアンサー

MacでC言語の勉強をフリーの処理系で楽しむならMacintosh Programer's Workshopが良いと思います。
PowerPC用のC/C++コンパイラ、MC68K用のC/C++コンパイラ、MC68Kのデバイスドライバ開発などに使えるアセンブラとMacプログラミング(Toolboxプログラミング)に必要なResEditなどのツールが全てそろっています。
http://developer.apple.com/tools/mpw-tools/

hohihohiさんご紹介のCodeWarriorも良いのですが、いかんせん高価なのでDiscover Programming for Macintosh日本語版リリース5(¥2、8000)程度で始められても良いかもしれません。
勉強に必要な入門書などがセットになっています。
ただし、2次生産物(作成したソフトウェア)の配布権などに制限がありますので実力がついたらCodeWarriorにアップグレード(¥4、1000)すると良いでしょう。
http://www.metrowerks.co.jp/Products/Discover/Discover_Mac5.htm

日本語による1年間のテクニカルサポートに¥2、8000をかけると思えば安いと思います。

MacでC言語の勉強をフリーの処理系で楽しむならMacintosh Programer's Workshopが良いと思います。
PowerPC用のC/C++コンパイラ、MC68K用のC/C++コンパイラ、MC68Kのデバイスドライバ開発などに使えるアセンブラとMacプログラミング(Toolboxプログラミング)に必要なResEditなどのツールが全てそろっています。
http://developer.apple.com/tools/mpw-tools/

hohihohiさんご紹介のCodeWarriorも良いのですが、いかんせん高価なのでDiscover Programming for Macintosh日本語版リリース5(¥2、8000)程...続きを読む

Q#define中の#のエスケープ

#defineを使ってincludeディレクトリを切り替えようと考えました。

-------
#define DIR_NAME"DIR_A"
//#define DIR_NAME"DIR_B"

#define ALL_INCLUDE(x)\
#include x##"/aaa.h"\
#include x##"/bbb.h"

ALL_INCLUDE(DIR_NAME)

-------

ですが#includeの#記号が文字列化の演算子と判断されてしまいます。
\#includeの場合、今度は改行のエスケープになってしまいます。

どうにかして#をエスケープさせることはできるでしょうか?

Aベストアンサー

ごめん, マクロの引数展開と文字列化との関係でマクロを 1つはさまないといけないことを忘れてた.
stringify の定義を
#define stringify(x) stringify_(x)
に変えて,
#define stringify_(x) #x
を追加したらどうだろうか.

ファイル名やディレクトリ名に空白が入るといろいろ問題になったりするが, この手法そのものがどっちかというとアレな部類に入るのでその辺は無視.


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング