cakealert 19 hours ago

This only applies to a situation where you have a function that requires dynamic checks for preconditions. I would suggest that such a function (or how it's being used) is likely a blight already, but tolerable with very few call sites. In which case checking at the call site is the right move. And as you continue to abuse the function perhaps the code duplication will prompt you to reconsider what you are doing.

  • jovial_cavalier 9 hours ago

    So if a function dereferences a pointer, it doesn't make sense to check that it's not null inside the function?

    Unless there's an actual performance implication, this is all purely a matter of taste. This is the kind of broadly true, narrowly false stuff that causes people to destroy codebases. "I can't write it this way, because I have to push ifs up and fors down!!!" It's a totally fake requirement, and it imposes a fake constraint on the design.

    • kazinator 6 hours ago

      If there is a performance implication of moving the if into the callers or not, you can do it with an inline function.

        static inline int function(blob *ptr, int arg)
        {
           if (ptr == NULL)
             return ERR_NULL;
           return real_function(ptr, arg);
        }
      
      Just like that, we effectively moved the if statement into 37 callers, where the compiler may be smart enough to hoist it out of a for loop when it sees that the pointer is never changed in the loop body, or to eliminate it entirely when it sees that the pointer cannot be null.
    • cakealert 9 hours ago

      IMO you should assert it's not null. There should never be a circumstance where you pass a null pointer to a function.

      • kazinator 5 hours ago

        ISO C allows:

          free(NULL); // convenient no-op, does nothing
        
          fflush(NULL); // flush all streams; done implicitly on normal exit
        
          time(NULL); // don't store time_t into a location, just return it
        
          strtol(text, NULL, 10);  // not interested in pointer to first garbage char
        
          setbuf(stream, NULL);  // allocate a buffer for stream
        
          realloc(NULL, size); // behave like malloc(size)
        
        and others. More examples in POSIX and other APIs:

          sigprocmask(SIG_UNBLOCK, these_sigs, NULL); // not interested in previous signal mask
        
          CreateEventA(NULL, FALSE, FALSE, NULL); // no security attributes, no name
        
        Reality just ran over your opinion, oops!
tylersmith 19 hours ago

You don't need an explicit rule, you just need to be smarter than than the average mid-curve tries-too-hard-to-feel-right hn poster and realize when you're repeating a calling convention too much.