简体   繁体   中英

why are complex null types used in c?

I'm working through some example code from Understanding Unix/Linux Programming (Bruce Molay) and I've seen a definition for a NULL utmp type:

 #define NULLUT  ((struct utmp *)NULL)

This null type used in methods such as:

 struct utmp *utmp_next()
 {
    ...
    if (no_more_records)
        return NULLUT;
 }

And the client code checks for the NULL utmp as such:

 int main()
 {
    ...
    while (( utbufp = utmp_next() ) != ((struct utmp *)NULL) )
       do_something()
 }

Why not have utmp_next() just return NULL from this method as defined in stddef.h and the while loop check for that instead?

The actual book source files are here:

For the most part, they're not. Most C programmers simply use the NULL macro, with a cast to the required pointer type only in the rare cases where it's necessary.

By defining a type-specific null pointer macro like

#define NULLUT  ((struct utmp *)NULL)

you get something that is only of that specific pointer type. Comparing a pointer of a different type, for example:

char *ptr = some_value;
if (ptr == NULLUT) /* ERROR */

the compiler will flag an error. A null pointer constant, on the other hand, is comparison-compatible with any pointer type.

I suppose the author thought that would be a good idea.

I disagree.

The macro NULL is standard, and every C programmer recognizes it. It's perfectly safe to use in a comparison, assignment, initialization, or return statement for any pointer type. And most of the time, it's perfectly safe to use as an argument to a function with a pointer parameter. The only exceptions are when the function has no visible prototype (solution: always use prototypes) or when it's a variadic function like printf (solution: cast NULL to the appropriate pointer type). (Macros using the new _Generic feature are probably another case where a cast might be needed.)

Defining your own NULLUT macro serves no real purpose that I can see.

while (( utbufp = utmp_next() ) != ((struct utmp *)NULL) )
   do_something()

This is from another source file from the book (the who3.c you cited in the question). Here, the author doesn't even define the NULLUT macro, choosing instead to write

((struct utmp *)NULL)

This would be better written as:

while (( utbufp = utmp_next() ) != NULL) )
   do_something()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM