Как проверить FILE * (указатель на структуру) (если == NULL)? - PullRequest
1 голос
/ 02 июня 2010

Я играл с C, в любом случае я думал, как можно проверить указатель файла (который указывает на тип структуры), если NULL, как на мгновение:

FILE *cfPtr;
if ( ( cfPtr = fopen( "file.dat", "w" ) ) == NULL )

Я пытался сделать это сам, но возникает ошибка.

struct foo{
    int x;
};

struct foo bar = {0};

if (bar == NULL)
    puts("Yay\n");
else
    puts("Nay");

ошибка C2088: '==': недопустимо для struct

Вот замедление ФАЙЛА в файле stdio.h:

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
        };
typedef struct _iobuf FILE;

Ответы [ 6 ]

10 голосов
/ 02 июня 2010

Это должен быть указатель на структуру:

struct foo* bar = ...

if (bar == NULL)
    puts("Yay\n");
else
    puts("Nay");

Указатели на структуры действительно могут быть проверены на нулевое значение, так же как указатели на примитивные типы.

4 голосов
/ 02 июня 2010

Вы должны позаботиться о различии между значением и указателем. Указатели содержат адрес значения - обычно (хотя и не всегда) значение, назначаемое с помощью malloc ().

В вашем примере

struct foo bar = {0};

if (bar == NULL)
    puts("Yay\n");
else
    puts("Nay");

бар расположен в стеке - это , а не указатель, поэтому вы не можете сравнить его с NULL (который является значением - фактически 0 в каждой используемой мной реализации).

Вы, вероятно, хотите что-то более похожее на

struct foo* bar = malloc(sizeof(struct foo));

if (bar == NULL)
    puts("Yay\n");
else
    puts("Nay");

bar->x = 0;

Обратите внимание, что вы не можете поместить значение в бар, пока не проверили, не является ли оно NULL. Если вы забудете об этом, вы получите ошибку разыменования нулевого указателя.

3 голосов
/ 02 июня 2010

Вы пытаетесь указать на то, что содержит ноль. Это не то же самое, что указатель со значением 0, который указывает на нулевой адрес его адресного пространства.

Страница man сообщает: «После успешного завершения fopen (), fdopen () и freopen () возвращают указатель FILE. В противном случае возвращается NULL и глобальная переменная errno устанавливается для указания ошибки."

В случае, если он возвращает 0, нет действительной структуры FILE, на которую можно указать.

2 голосов
/ 02 июня 2010

FILE *p является указателем и имеет смысл сравнить его со значением NULL. С другой стороны,

struct foo bar = {0};

if (bar == NULL)

не имеет смысла (по крайней мере, тот, который вам нужен), и не имеет ничего общего с &bar == NULL; последний будет работать, но всегда будет ложным, так как память struct foo bar = {0} точно существует. Так что на самом деле не существует способа, как может произойти сбой для struct foo bar;: память «правильно распределена» или программа дает сбой другим способом.

struct foo *bar;
bar = malloc(sizeof(struct foo));
if ( bar == NULL ) // ...

говорит, что bar является указателем (и мы пытаемся распределить необходимую память для хранения struct foo), поэтому bar == NULL в порядке.

Вы можете сказать что-то вроде FILE p, которое отличается от FILE *p (и не рекомендуется, FILE * должен рассматриваться как "непрозрачный" указатель, который вас не должен интересовать, поскольку он может отличаться в разных реализациях )

Добавить после прочтения комментария автора вопроса

FILE *cfPtr;
if ( ( cfPtr = fopen( "file.dat", "w" ) ) == NULL )

Это работает, так как сначала оценивается left inner (), и поэтому cfPtr присваивается результату fopen, как если бы это был единственный statemente cfPtr = fopen(...). После этого этот же результат (значение cfPtr) сравнивается с NULL. fopen возвращает, конечно, FILE *, и указатель можно сравнить с NULL.

0 голосов
/ 02 июня 2010

если ваш Q как этот код работает:

if ( ( cfPtr = fopen( "file.dat", "w" ) ) == NULL ) ? 

==> эквивалентно

  1. cfPtr = fopen( "file.dat", "w" ) // Обратите внимание, что fopen возвращает FILE*, который получает // присваивается cfPtr

  2. if( cfPtr == NULL)

0 голосов
/ 02 июня 2010

Может быть, вы можете проверить некоторые из его членов? Может быть, _ptr или _tmpfname, например?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...