FILE的数据类型是什么?

6

FILE在C语言或其他语言中的数据类型是什么?

FILE既不是整数也不是结构体,它没有特定的数据类型。


5
为何不在记事本中打开 stdio.h 文件。 - Ed Heal
2
我不明白为什么这个问题被踩。我也不知道答案,想学习。而做man stdio并不是一个答案。你可以用 man xxx回答90%的stackoverflow问题。 - stackoverflowuser2010
+1,我想知道在头文件中是否可以前向声明struct FILE;(不包括<stdio.h>)以减少命名空间污染,我认为它可以在大多数系统上工作,但标准并不要求。这绝对是一个有效的问题。但是,“或者用其他语言”这句话是什么意思?这可能取决于语言,而你只标记了C和C++… - mafso
@JimBalter 嗯,<stdio.h>中有完整的FILE结构定义和只有前向声明的主要功能差异之一是,你需要完整的定义来自己声明一个FILE(或其数组)。所以这就是它们之间的联系。 - user149341
2
请看这里什么是不透明值? - Deduplicator
显示剩余9条评论
2个回答

13

你提出的不透明数据类型实现在C语言中是未定义行为...你不能将“简单结构”(无论它是什么)强制转换为“实际数据类型”。而且这也不是通常的实现方式...请参考duskwuff的答案获取一个实际示例。 - Jim Balter
这取决于具体的实现,但是库经常使用不透明数据类型... 你正在使用一个指向不透明类型的指针,并且在代码中传递该指针,但从未直接对其进行解引用... 由于它是一个指针,你可以将其转换为任何必要的类型。 - Jason
P.S. Deduplicator已经发布了如何做到这一点的链接:https://dev59.com/3m865IYBdhLWcg3wW9RE - Jim Balter
阅读标准...您不能将一个指向一个结构类型的指针强制转换为指向另一个结构类型的指针,然后对其进行解引用,除非其中一个结构是另一个结构的第一个成员。正确的解决方案由链接中的paxdiablo给出,显然不是您描述的那样,因为没有“简单结构”和没有转换...在调用者和实现中都是相同的struct xyzzy,但只有实现才能访问结构的成员。 - Jim Balter
我确实看了paxdiablo的答案,但我仍然相信这不是未定义行为。原因是根据标准,您可以从T*转换为U*,再转回T*,并且只要对齐正确,标准明确指出这不是未定义行为。因此,库创建了一个内部的T*,通过转换将用户从库函数传递给不透明类型U*...用户不会解引用此指针,而是在另一个调用中将其传回库,此时库将其重新转换为最初定义的非不透明T*...这不是未定义行为。 - Jason
显示剩余3条评论

11

这是一个typedef,用于包含有关文件句柄状态的数据的结构体。结构体的确切内容因系统而异,在我的系统(Mac OS X)中,定义如下:

/*
 * stdio state variables.
 *
 * The following always hold:
 *
 *      if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
 *              _lbfsize is -_bf._size, else _lbfsize is 0
 *      if _flags&__SRD, _w is 0
 *      if _flags&__SWR, _r is 0
 *
 * This ensures that the getc and putc macros (or inline functions) never
 * try to write or read from a file that is in `read' or `write' mode.
 * (Moreover, they can, and do, automatically switch from read mode to
 * write mode, and back, on "r+" and "w+" files.)
 *
 * _lbfsize is used only to make the inline line-buffered output stream
 * code as compact as possible.
 *
 * _ub, _up, and _ur are used when ungetc() pushes back more characters
 * than fit in the current _bf, or when ungetc() pushes back a character
 * that does not match the previous one in _bf.  When this happens,
 * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
 * _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
 *
 * NB: see WARNING above before changing the layout of this structure!
 */
typedef struct __sFILE {
        unsigned char *_p;      /* current position in (some) buffer */
        int     _r;             /* read space left for getc() */
        int     _w;             /* write space left for putc() */
        short   _flags;         /* flags, below; this FILE is free if 0 */
        short   _file;          /* fileno, if Unix descriptor, else -1 */
        struct  __sbuf _bf;     /* the buffer (at least 1 byte, if !NULL) */
        int     _lbfsize;       /* 0 or -_bf._size, for inline putc */

        /* operations */
        void    *_cookie;       /* cookie passed to io functions */
        int     (*_close)(void *);
        int     (*_read) (void *, char *, int);
        fpos_t  (*_seek) (void *, fpos_t, int);
        int     (*_write)(void *, const char *, int);

        /* separate buffer for long sequences of ungetc() */
        struct  __sbuf _ub;     /* ungetc buffer */
        struct __sFILEX *_extra; /* additions to FILE to not break ABI */
        int     _ur;            /* saved _r when _r is counting ungetc data */

        /* tricks to meet minimum requirements even when malloc() fails */
        unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
        unsigned char _nbuf[1]; /* guarantee a getc() buffer */

        /* separate buffer for fgetln() when line crosses buffer boundary */
        struct  __sbuf _lb;     /* buffer for fgetln() */

        /* Unix stdio files get aligned to block boundaries on fseek() */
        int     _blksize;       /* stat.st_blksize (may be != _bf._size) */
        fpos_t  _offset;        /* current lseek offset (see WARNING) */
} FILE;

struct __sbuf 是一个在此 stdio 实现中用于存储数据缓冲区的结构体,定义如下:

struct __sbuf {
        unsigned char   *_base;
        int             _size;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接