17

FILE *Cで前方宣言するにはどうすればよいですか?私は通常これを使用してこれを行いますstruct MyType;が、当然これは可能ではないようです。

C標準またはコンパイラ間およびC++で動作が異なる場合、これも重要です。

Update0

これを脇に置きたい理由:私が求めているのは、非struct / "typedef'd struct"型を前方宣言して、それへのポインターを宣言できるようにする方法です。明らかに、それを使用void *してソースファイルにキャストするのは少しハックです。

4

6 に答える 6

25

できません。この規格FILEは、「ストリームを制御するために必要なすべての情報を記録できるオブジェクトタイプ」であると述べています。これが(とにかく名前がわからない)のか、それとも他の何かかは、実装typedef次第structです。

宣言する唯一の移植可能な方法FILEは、with #include <stdio.h>(または<cstdio>C ++)です。

于 2010-10-07T14:03:35.583 に答える
11

あなたがそれでtypedefを#include <stdio.h>取得する必要がある場合。FILEこれが唯一の本当に安全で移植性のある方法です。エイリアスする型がないとtypedefを使用できず、どの型FILEエイリアスであるかについての保証はありません。したがって、すべてのコンパイラやlibcなどが異なるものを持つことができます。#include <stdio.h>しかし、一貫性のない定義がエラーを引き起こさないように、誰かが実際にそうしたい場合に備えて、タイプが正しい必要があります。

編集:

今考えてみると、もう一つ考えられる方法があるかもしれません。これはtypedefではなく、「FILE」の定義を乗っ取って機能する邪悪なマクロです。その理由だけではお勧めしません。しかし、それはあなたが必要とするもののために働くかもしれません。

#ifdef USES_REAL_FILE_TYPE
#include <stdio.h>
#else
#define FILE void
#endif

/* declare your struct here */

#ifndef USES_REAL_FILE_TYPE
#undef FILE
#endif

次に#define USES_REAL_FILE_TYPE、実際のが必要なコードにファイルを含める前にFILE *、残りのコードはポインターを。として表示しますvoid *

私はこれが物事を台無しにしないことを保証しません。特に、そのような偽の型について実際に何かを知りたい場合は壊れ、ポインタに触れるすべてのコードでその#defineが必要になる場合があります。しかし、「不要な」#includesに完全に反対している場合はFILE *、stdioに干渉せずにそれを取得する唯一の方法です。typedefを前方宣言することはできません。

Edit2:

OK、念のためチェックしました。それがどれほど標準的であるか、またはあなたがそれで何ができるかはわかりませんが...

typedef FILE;

Visual CとGCCの両方で機能しますが、 Cコードをコンパイルする場合に限ります。C ++標準では、型なしではtypedefを使用できないと明示的に示されているように見えます。ただし、Cのものはそうではありません。

ただし、GCCではなく、型を前方宣言することはできないようです。typedef int FILE;すぐに実行しようとすると、typedefの競合に関するエラーがスローされます。ただし、VSは、整数型である限り、それを許可しているようです。VSでは(そして明らかにC99では)本当にtypedef X意味があるようです。typedef int Xいずれにせよ、GCCでは、まったく同じタイプであっても、typedefをやり直すことはできません。

于 2010-10-07T14:01:58.580 に答える
6

FILEは、専用のAPI関数を使用しない限り、(WinAPIハンドルの背後にあるデータを操作することは想定されていないように)あまり探索することを想定していない構造体の周りのtypedefです。

フォワード宣言?

Forward-declaringを使用すると、型へのポインター(または、C ++では参照)を宣言し、シンボルが使用されていない限り、その宣言をコンパイルできます(たとえば、ヘッダーにシンボルを転送宣言してから、シンボルがそれを使用してソースで適切に宣言されているヘッダー)。

したがって、前方宣言には次の手段が含まれます。

  • より高速なコンパイル
  • カップリングが少ない

チャックTypedef対フォワード宣言?

typedefの問題は、ご存知のように、前方宣言できないため、処理が面倒なことです。

したがって、前方宣言するFILEことも、前方宣言することもできませんstd::string。したがって、それらを処理するためのヘッダーを含める以外に選択肢はありません。

(これが、CがC ++コードに侵入する際のtypedefパターンを嫌う理由ですstruct { /* ... */ } MyTypedefedType ;。C++では役に立たず、前方宣言が妨げられます。)

前方宣言標準記号?

良い部分は、シンボルが「標準」である場合、それらのヘッダーを含めるのにそれほど苦痛であってはならないということです。結合はそれほど問題ではありません。コンパイルが多少遅くなる場合でも、プリコンパイル済みヘッダーを使用することで問題を解決できます。

<iosfwd>:あなたのことを考えている人もいます!

C++標準ライブラリは<iosfwd>ヘッダーを提供します。

C ++ストリームヘッダーの一部(またはすべて)を含める代わりに、<iosfwd>必要なのが前方宣言のみであるかどうかを含めることができます。

于 2010-10-09T09:51:03.517 に答える
4

FILEシステムに依存しtypedefます。実際の構造がどのように定義されているか、あるいは名前が付けられているかを気にする必要はありません。しかし、あなたはいつでもあなたのファイルを調べることができ/usr/include/stdio.hます:)

于 2010-10-07T14:02:10.763 に答える
0

すでに指摘したように、FILE構造体または型定義を前方宣言する移植可能な方法はありません。

ただし、プレーン整数に依存するように独自のファシリティのインターフェイスを変更してから、fileno関数(を介して使用することもできます#include <stdlib.h>)を使用することができます。

詳細な手順
0.現在のインターフェースを見つけます。次に例を示します
    void myprint(FILE* stream, ...);
。1。:の代わりに整数ファイル記述子(fd)を使用します。2。:の代わりにでFILE*新しいインターフェイス
    void myprint(int stream_fd, ...);
を呼び出します。filenoFILE*
    myprint(fileno(stream));

ただし、欠点は、実際のI / Oルーチンではmyprintなく、ファイル記述子を使用して実装(上記の例)を書き直す必要があることです。FILE*実装を書き直す代わりに、指定された記述子を使用することもfdopenできます。FILE

void myprint(int stream_fd, ...)
{
  FILE *const stream = fdopen(stream_fd);
  /* your existing implementation follows */
  fclose(stream);
}

上記により、リソースを「所有する」場所について考え、FILE不要になったときにリソースを閉じることができます。多くの場合、オープン/クローズシーケンスは(上記のように)問題ありませんが、より複雑なケースでは、追加モードなどを使用してファイルを開くことにより、実装を調整する必要があります(回避しようとしました)。

于 2016-01-06T10:46:14.703 に答える
-3

FILE*は不透明(OPAQUE)型です。したがって、これは理論的には機能するはずです。

typedef struct FILE_impl_but_including_stdio_h_is_best FILE;
于 2010-10-07T14:12:34.080 に答える