0

I've been programming with SDL for a while, and I decide to make a header file to simplify my coding. Now I have a question; if I pass a function parameter I don't want, should I do

test(NULL);

from the Windows API I include or

test(false);

I use C++, NOT C.

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
NDSgrammer
  • 43
  • 1
  • 4
  • 1
    are you referring to the C++ 0x `nullptr`? – Timo Geusch Mar 10 '11 at 00:49
  • Whoops: I'm sorry. I typed null instead of false! I'm bad >:) – NDSgrammer Mar 10 '11 at 00:55
  • NULL is just a define for 0 or 0L. null pointer signifies that the pointer does not point to an object. It's a matter of preference, but since we do not have the function definition, it is hard to tell what you really mean. –  Mar 10 '11 at 01:23

4 Answers4

2

It completely depends on what the function parameter type is. If it's a pointer, and the documentation says that it's valid, then you can pass the C++ NULL (which is just 0 in reality).

Examples:

// Bad; strlen expects a pointer to a real, existing C-string buffer
std::cout << strlen(NULL);

/**
 * Function that does something.
 * 
 * @param ptr Pointer to buffer, or NULL to do nothing
 */
void myFunc(const char* ptr);

// OK; the function is designed to be ok with it
myFunc(NULL);

So not all functions will accept this as valid for a pointer.

It certainly won't be valid for any other type (though you'll get away with passing it for an int, it's not quite what you'd expect to do). NULL is not a catch-all "I want to opt out of this function parameter". You simply can't do that in the general case.

Conclusion: It depends what test is.

And I have no idea what null is supposed to be.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • `#define null NULL`, perhaps. –  Mar 10 '11 at 00:49
  • 1
    Note that `sscanf` is a varargs function and `NULL` is just an integer, not a pointer, so `NULL` gets passed as a `int`, not a pointer. Even if `sscanf` did support passing `NULL` for `%s`, it wouldn't necessarily work without a typecast. – bk1e Mar 10 '11 at 02:08
  • @bk1e: Yea, bad example, perhaps. Have edited with a better one. Thanks! – Lightness Races in Orbit Mar 10 '11 at 10:43
1

Tomalak's answer is great advice for calling existing functions. When you're writing a function (or when you are free to change the function) and you want parameters to be optional, you should try to design it so the usage is correct, intuitive and self-documenting. If we compare:

1) bool really_test = ...;
   test(really_test, my_test);
2) if (...)
       test(my_test);
3) test(... ? &my_test : NULL);

2) is more comprehensible for using if - a universally understood keyword, and not simply implying that the function's first argument can be set to bypass the test. The dangerous scenario is that someone writes code like 3) misremembering or misunderstanding the API; it works happily until that NULL condition is satisfied (which might be in prod rather than testing).

Similarly, when some behaviour is optional, I prefer to use an enum to document those options instead of a boolean that communicates nothing at the call site. Contrast...

test(false);
test(true);

...with...

test(Text_Output);
test(Html_Output);

If there are multiple arguments, then it can be useful to use a sentinel such as NULL to indicate that some of them aren't applicable. It's harder to get this wrong if the arguments are of distinct type:

test(my_test, /* output stream */ NULL, &error_counter, /* skip list */ NULL);

In such usage, you can expect a compile-time error if an argument is accidentally omitted or the order is wrong.

When the compiler can't check the argument order/count it's dangerous:

test(&my_test /* mandatory, this one has three stages */,
     /* stderr else out */ true, /* update counters */ false,
     /* skip 1st stage */ true, /* skip 2nd */ false, /* skip 3rd */ true);

That might satisfy...

test(Test*, bool use_error_stream, bool update_counters, ...);

...which would be a spectacularly bad API.

Note that references mandatorily point to a valid object, so some people like to use them where possible to communicate the fact the option is mandatory. Other people think it's more important to hint at whether a parameter is modifiable at the call site, and write functions accepting non-const pointers:

f(my_object);  // obviously mandatory, but is it const or not?

f(&my_object); // _might_ be modifiable (if that conventions followed),
               // but is it mandatory or not?
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
0

null is a Java (and C#) keyword. It has no business showing up in C++ code.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

nullptr is the way to go. VC++10 already supports it. GCC will support it in 4.6

Community
  • 1
  • 1
t.g.
  • 1,719
  • 2
  • 14
  • 25
  • The OP was trying to use `NULL` or `false` as a way to opt-out of passing an arbitrary argument. Using `nullptr` is no more correct. – Lightness Races in Orbit Mar 10 '11 at 10:46
  • @Tomalak, you are right here. I was misled by the title.The issue is actually NOT about a choice between NULL or false, but a value that can be implicitly cast to any type. NULL is not the answer as you've illustrated in your answer above, and probably there's no answer as C++ is a strong-typed language. – t.g. Mar 11 '11 at 06:48