Harald van Dijk said:
Agreed, but...
...is there anything in C90 that supports this idea? You're saying that
void assert(int expression);
has a meaning that differs in important areas from the exact same syntax
used to declare a function named assert, that since it isn't a prototype,
it shouldn't be read as one. Yet at the same time you're saying this
prototype-lookalike *should* be read as a prototype when determining the
accepted type of the macro argument. I would expect the conclusion to be
that the prototype-lookalike should be ignored entirely. Why is that not
so?
The description of assert() in C90 was flawed. That standard used
something that looks like a prototype to illustrate how the assert
macro is to be used, but since it's required to be a macro, there's no
reasonable definition of assert() that would maintain the full
semantics required if it were a prototyped function (particularly the
implicit declaration to int for an argument of any arithmetic type).
Because of this, it's very difficult to argue that the behavior of
assert() with, say, a floating-point argument was well defined.
C99 improved the definition by providing a pseudo-prototype:
void assert(scalar expression);
Because it can't be a real prototype, we're left with the idea that it
can accept any arbitrary scalar expression; the description is also
clearer.
It's quite possible that all existing C90 implementations of assert()
work as expected for non-int scalar arguments (the most
straightforward implementation would work that way; you'd have to
expend extra effort to make non-int expressions fail). But since the
C90 standard didn't guarantee this, it was safest not to depend on it.
Replacing ``assert(expr)'' with ``assert(expr != 0)'' would suffice to
force the argument to be of type int, making the invocation safe.