Если вы #include <stdio.h>
, вы должны получить вместе с ним FILE
typedef. Это единственный действительно безопасный и переносимый способ - у вас не может быть 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.
Редактировать2:
Хорошо, я проверил, чтобы убедиться. Не уверен, насколько это стандартно или что с ним можно сделать, но...
typedef FILE;
работает как в Visual C, так и в GCC, но только при компиляции кода C. Может показаться, что в стандарте С++ где-то явно сказано, что у вас не может быть typedef без типа. C, однако, нет.
Тем не менее, похоже, что тип не может быть объявлен заранее, во всяком случае, не в GCC. Если вы попытаетесь typedef int FILE;
сразу после этого, выдается ошибка о конфликте определений типов. Однако VS, похоже, позволяет это, если он имеет целочисленный тип. Кажется, typedef X
действительно означает typedef int X
в VS (и, видимо, в C99). В любом случае, GCC не позволит вам переопределить typedef даже для точно такого же типа.
person
cHao
schedule
07.10.2010
stdio.h
? Дело не в том, чтоstdio.h
часто меняется и сокращает время добавочной сборки. - person jamesdlin   schedule 07.10.2010<stdio.h>
там, где это не нужно, просто следует хорошей практике. К сожалению для OP, это невозможно сделать сFILE
, потому что этоtypedef
. - person Dan Moulding   schedule 07.10.2010#include
— это прямой способ сократить время компиляции, которое не зависит от нестандартных функций компилятора, зависящих от реализации. - person Dan Moulding   schedule 07.10.2010stdio.h
, поэтому, по-моему, избегание его в заголовочном файле, который в нем нуждается, имеет сомнительную ценность. Если окажется, что это действительно имеет значение, то разбейте заголовочный файл. - person jamesdlin   schedule 07.10.2010stdio.h
, будет зависеть от конкретных обстоятельств, в которые никто из нас (за исключением OP) не в курсе. Все, что я говорю, это то, что сведение к минимуму использования#include
в целом является хорошей практикой и может быть в данном случае веской причиной для OP изучить эту строку допрос. - person Dan Moulding   schedule 07.10.2010#include
путем создания прототипов для функций, типов и т. д., о которых вы не знаете, является ужасно плохой практикой. Если вам нужен ФАЙЛ по какой-либо причине, это потому, что вы делаете что-то с функциями stdio и должны#include <stdio.h>
в любом случае. Не включайте то, чем не пользуетесь, но если используете, включите. - person cHao   schedule 08.10.2010FILE *
. Представьте себе далее, что многим исходным файлам необходимо использовать эту структуру, но только один исходный файл выполняет какой-либо файловый ввод-вывод с использованиемFILE *
. В этом случае была бы удобна возможность пересылки объявленияFILE
(а в противном случае#include <stdio.h>
было бы не нужно). - person Dan Moulding   schedule 08.10.2010FILE *
не нужен в 9/10 всего кода, который касается этой структуры, возможно, его не должно быть там в первое место. - person cHao   schedule 08.10.2010FILE *
, и только Logger.cpp выполняет любой файловый ввод-вывод, используя этот частныйFILE *
, тогда что-то не так с моим дизайном, потому что другой 99 файлов, все из которых используютLogger
, не выполняют файловый ввод-вывод? Надеюсь, вы понимаете мою точку зрения. 99 файлов должны (косвенно) включать<cstdio>
(поэтому он компилируется 99 раз), даже если только один файл фактически выполняет какой-либо файловый ввод-вывод. - person Dan Moulding   schedule 08.10.2010<cstdio>
. Как и должно быть, поскольку класс содержитFILE *
. Вам нужен стандартный тип библиотеки, вы включаете заголовок, который его определяет; вы не наполовину декларацию. Период. Меня не волнует, если это увеличивает время сборки. Не нужно задаваться вопросом, используете ли вы стандартныйstruct tm
илиFILE
или что-то еще.#include
не только определяет тип, но и говорит, что я использую материал, определенный стандартной библиотекой, а не какое-то пользовательское дерьмо с тем же именем (поскольку переопределение типа вызовет ошибку компиляции). - person cHao   schedule 08.10.2010FILE *
. На самом деле структура контекста аналогичным образом объявляется в общедоступном интерфейсе библиотеки, поэтому внутренние компоненты скрыты. Мне не нужно или я не хочу, чтобы другие исходные файлы содержали подпрограммы ввода-вывода. Если быFILE *
не было объявлено заранее, пользовательский тип, содержащий его, был бы таким, что подразумевало бы дополнительное выделение памяти и потенциальные ошибки. - person Matt Joiner   schedule 08.10.2010FILE
, и поэтому возник этот вопрос — как я объяснял @Oli и @jamedlin . К сожалению, вы не можете пересылать объявленияtypedef
s. Но я повторю еще раз: использование предварительных объявлений, когда все, что нужно, это неполный тип, является разумной практикой. Включение вместо этого полного определения структуры через включение ее заголовка является ненужным и расточительным (хотя это обычная практика, потому что это проще, чем думать о том, подойдет ли только неполный тип). - person Dan Moulding   schedule 08.10.2010