tags:

views:

129

answers:

6

I was playing around with C, anyways I was thinking how can file pointer (which points to a struct type), be tested if NULL as for instant:

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

I tried to do that myself, but an error occurs.

struct foo{
    int x;
};

struct foo bar = {0};

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

error C2088: '==' : illegal for struct

Here's the FILE deceleration in the stdio.h file:

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

Maybe you can test some of its members? Maybe _ptr or _tmpfname, for instance?

Vnuce
I that, my question is how can this code work: if ( ( cfPtr = fopen( "file.dat", "w" ) ) == NULL )?
m4design
I just tried if((cfPtr = fopen("file.dat","w")) == NULL) return 1; and it compiled OK.
Vnuce
@m4design: Your question is clear, however in your examples `cfPtr` is a pointer while `bar` *is not* ; it is an instance of a struct, not a pointer to a struct. Use "struct foo* bar = 0` instead.
Clifford
@Vnunce: I think you have misunderstood m4design's question. He simply wants to know why his code does not work when the FILE* example does. The answer is simply that he is not using a pointer at all in his example.
Clifford
@Clifford: Yup... I totally missed the idea of the question. I need coffee :)
Vnuce
+10  A: 

It should be a pointer to a struct:

struct foo* bar = ...

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

Pointers to structs can indeed be tested for nullness, just as pointers to primitive types.

Péter Török
+3  A: 

You are trying to point to something that contains a null. That's not the same as a pointer with the value 0, which points to the address null of its address space.

The manpage says: "Upon successful completion fopen(), fdopen() and freopen() return a FILE pointer. Otherwise, NULL is returned and the global variable errno is set to indicate the error."

In the case that it returns 0 there is no valid FILE struct to point to.

Eddy Pronk
+3  A: 

You must take care of the distinction between a value and a pointer. Pointers hold the address of a value - usually (although not always) a value allocated using malloc().

In your example

struct foo bar = {0};

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

bar is allocated on the stack - it is not a pointer, so you cannot compare it with NULL (which is a value - in fact 0 on every implementation I have used).

You probably want something more like

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

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

bar->x = 0;

Notice that you cannot put a value into bar until you have checked whether it is not NULL. If you forget this you will get a NULL pointer dereference error.

Jeremy O'Donoghue
A: 

if your Q is how can this code work:

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

==> its equivalent to

  1. cfPtr = fopen( "file.dat", "w" ) //Note that, fopen returns FILE* that gets //assigned to cfPtr

  2. if( cfPtr == NULL)

aJ
+2  A: 

FILE *p is a pointer and it is meaningful to compare it with NULL value. On the other hand,

struct foo bar = {0};

if (bar == NULL)

makes no sense (not the one you want at least), nor it does a thing like &bar == NULL; the latter would work, but would be always false, since struct foo bar = {0} 's memory exists for sure. So indeed there's no way how there can be a failure for struct foo bar;: the memory is "allocated" correctly or the program fails some other way.

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

says that bar is a pointer (and we try to malloc the needed memory to hold struct foo), and so bar == NULL is ok.

You can say somethig like FILE p which is different from FILE *p (and not suggested, FILE * must be considered an "opaque" pointer you shouldn't be interested to, since it may be different in different implementation)

Add after reading a comment of the asker

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

This works since first the left inner () is evaluated, and so the cfPtr is assigned to the result of fopen, like if it were an alone statemente cfPtr = fopen(...). After that, this same result (the value of cfPtr) is compared to NULL. fopen returns a FILE * of course, and a pointer can be compared to NULL.

ShinTakezou