Checking for null before pointer usage

后端 未结 13 2574
孤独总比滥情好
孤独总比滥情好 2021-02-20 09:32

Most people use pointers like this...

if ( p != NULL ) {
  DoWhateverWithP();
}

However, if the pointer is null for whatever reason, the functi

13条回答
  •  情书的邮戳
    2021-02-20 10:02

    In addition to the other answers, it depends upon what NULL signifies. For example, this code is perfectly OK, and is pretty idiomatic:

    while (fgets(buf, sizeof buf, fp) != NULL) {
        process(buf);
    }
    

    Here, NULL value indicates not only error, but end-of-file condition as well. Similarly, strtok() returns NULL to say, "there are no more tokens" (although one should avoid strtok() to begin with, but I digress). In cases like this, it is perfectly OK to call a function if the returned pointer is not NULL, and do nothing otherwise.

    Edit: another example, closer to what was asked:

    const char *data = "this;is;a;test;";
    const char *curr = data;
    const char *p;
    while ((p = strchr(curr, ';')) != NULL) {
        /* process data in [curr, p) */
        process(curr, p);
        curr = p + 1;
    }
    

    Once again, NULL here is an indication from strchr() that it couldn't find a ;, and that we should stop processing the data further.

    Having said that, if NULL is not used as an indication, then it depends:

    • If the pointer can't be NULL at this point in code, it's useful to have an assert(p != NULL); when developing, and also having a fprintf(stderr, "Can't happen\n"); or equivalent statement, and then take whatever action as appropriate (abort() or similar is probably the only sane choice at this point).
    • If the pointer can be NULL, and it's not critical, it might be better to just bypass the usage of the null pointer. Suppose you're trying to allocate memory for writing a log message, and malloc() fails. You shouldn't abort the program because of this. If malloc() succeeds, you want to call a function (sprintf()/whatever) to fill the buffer.
    • If the pointer can be NULL, and it's critical. In this case, you probably want to fail, and hopefully such conditions don't happen too often.

    Secondly, consider you have a function that takes a pointer as an argument, and you use this function multiple times on multiple pointers throughout your program. Do you find it more beneficial to test for NULL in the function (the benefit being you don't have to test for NULL all over the place), or on the pointer before calling the function (the benefit being no overhead from calling the function)?

    This depends upon a lot of factors. If I can be sure sometimes or most of the times that the pointer passed to a function cannot be NULL, the extra check in the function is wasteful. If the pointer passed comes out of a lot of places, and it's tricky to put in a check everywhere, sure, then the check is good to have in the function itself.

    The standard library functions, for the most part, don't check for NULL: str*, mem* functions for example. An exception is free(), it does check for NULL.

    A comment about assert: assert is a no-op if NDEBUG is defined, so one should not use it for debugging—its only use is during development to catch programming errors. Also, in C89, assert takes an int, so assert(p != NULL) is better in such cases than a just plain assert(p).

提交回复
热议问题