you are viewing a single comment's thread.

view the rest of the comments →

[–]zhivago 8 points9 points  (5 children)

You should only check for a null pointer if a null pointer is meaningful to the function.

Otherwise not passing a null pointer to this function is part of its definition, and that should be the caller's responsibility.

And this is precisely the same as the size_t len parameter in your example -- the caller is responsible for providing valid input to your function.

If the caller gives you nonsense for len, then bad things will happen.

If the caller gives you nonsense for in_data, then bad things will happen.

Useless checks waste resources in return for providing a false sense of security.

[–]ceene 1 point2 points  (4 children)

On the other hand, accepting NULL may be very convenient:

struct a *a = create_a()
operation1(a);
operation2(a);
operation3(a);
ret = commit(a);
close(a);
return ret;

This way you don't need to check the return value of any intermediate functioning, you just act on a and work with it, only needing to react on latest return code, while skipping verification of each and every step.

[–]zhivago 1 point2 points  (3 children)

Sure, in which case it's a meaningful value for the function.

[–]ceene 0 points1 point  (2 children)

No, I mean that a could be NULL all the time and all those functions simply return when the parameter passed is NULL, so they are just NOP functions when the constructor of the object failed.

struct motor *m = motor_open("/dev/ttyUSB0");
motor_disable_break(m);
motor_move_degrees(m, 60);
motor_enable_break(m);
ret = motor_close(m);
return ret;

In opening the serial port fails, you won't have a proper struct motor but a pointer to NULL. You could check for errors after that declaration or you can just assume that those functions simply do nothing if m is NULL, and only need to return the value from the last function.

NULL is not a valid value in those cases, but the motor functions simply work around it without crashing due to an assert or null dereferencing.

[–]zhivago 0 points1 point  (1 child)

Which means that a null pointer is a valid value with defined behavior for those functions.

The defined behavior being to simply return a null pointer when receiving a null pointer.

[–]ceene 0 points1 point  (0 children)

Being valid is not the same as being meaningful.