assert must take int?

  • Thread starter Tomás Ó hÉilidhe
  • Start date
T

Tomás Ó hÉilidhe

In C89, do we have to pass an int as an argument to assert? I've got code
at the moment that does an assertion on pointer, e.g.:

assert(p);

, but I'm wondering if I should change that to:

assert(0 != p);
 
B

Ben Bacarisse

Tomás Ó hÉilidhe said:
In C89, do we have to pass an int as an argument to assert? I've got code
at the moment that does an assertion on pointer, e.g.:

assert(p);

, but I'm wondering if I should change that to:

assert(0 != p);

Yes, in C89 the prototype is for an int. In C99 this has been changed
to any scalar expression (of course you can't write that as a
prototype but that is the implementation's problem, not yours).
 
T

Tomás Ó hÉilidhe

Yes, you should (or use an equivalent such as assert(p != 0) or
assert(p != NULL) etc).



Thanks for the info. I only came across the problem when I changed
compilers recently, I got a boat-load of warnings about conversions from
pointers to integer type :-O

Looks like I'll be doing a "Find in files" for "assert" :p

(I shudder to think what my previous compiler was actually doing... was it
taking the pointer as a scalar or was it doing something... dirty... )
 
R

Richard Heathfield

Tomás Ó hÉilidhe said:
In C89, do we have to pass an int as an argument to assert? I've got code
at the moment that does an assertion on pointer, e.g.:

assert(p);

4.2.1.1 The assert macro

Synopsis

#include <assert.h>
void assert(int expression);

So you have to provide an int. If you don't, the behaviour is undefined.

(As you seem to have guessed, in C99 this has changed, and the expression
only has to be scalar - the restriction to int has been lifted.)
, but I'm wondering if I should change that to:

assert(0 != p);

Yes, you should (or use an equivalent such as assert(p != 0) or assert(p !=
NULL) etc).
 
R

Richard Tobin

(I shudder to think what my previous compiler was actually doing... was it
taking the pointer as a scalar or was it doing something... dirty... )

Your previous compiler was doing what most compilers have always done:
define assert as a macro something like

#define assert(e) \
((void) ((e) ? 0 : __assert (#e, __FILE__, __LINE__)))

(that's the definition in MacOS X). The asserted expression is used
as a conditional, so it works perfectly well with a pointer. That
this is the Right Thing is confirmed by the change in C99.

The restriction in C90 was clearly a mistake; I'm not sure where it
came from.

-- Richard
 
M

Martin Ambuhl

Tom�������������������������������� said:
In C89, do we have to pass an int as an argument to assert?

No, you need to pass an expression that yields a value of any integer
type (and some implementations accept any scalar type, although that is
not guaranteed).
I've got code
at the moment that does an assertion on pointer, e.g.:

assert(p);

Since pointers are not of an integer type, this is not a good idea.
, but I'm wondering if I should change that to:

assert(0 != p);

That is probably a good idea.
It is also a good idea to remember that the result of a failed assert
can often be extreme consternation, puzzlement, and anger on the part of
a user. Remember to define NDEBUG for any code outside of the testing
stage, even if you consider using the assert macro a good debugging
technique.
 
H

Harald van Dijk

Tomás Ó hÉilidhe said:

4.2.1.1 The assert macro

Synopsis

#include <assert.h>
void assert(int expression);

So you have to provide an int. If you don't, the behaviour is undefined.

The "prototype" would allow for an implicit conversion to int, if there
isn't any statement suggesting otherwise, so it would mean that C90
requires assert(0.5) to fail. It would also mean that assert(p); is a
constraint violation, rather than undefined behaviour. Does C90 have
relevant text on either of these points in what follows?
 
G

Golden California Girls

Martin said:
No, you need to pass an expression that yields a value of any integer
type (and some implementations accept any scalar type, although that is
not guaranteed).

Since pointers are not of an integer type, this is not a good idea.


That is probably a good idea.
It is also a good idea to remember that the result of a failed assert
can often be extreme consternation, puzzlement, and anger on the part of
a user. Remember to define NDEBUG for any code outside of the testing
stage, even if you consider using the assert macro a good debugging
technique.

Or perhaps rewriting it so it says something more like "Call 1-800-HELP-DESK and
read us the rest of this message."
 
C

CJ

Tomás Ó hÉilidhe said:


4.2.1.1 The assert macro

Synopsis

#include <assert.h>
void assert(int expression);

So you have to provide an int. If you don't, the behaviour is undefined.

(As you seem to have guessed, in C99 this has changed, and the expression
only has to be scalar - the restriction to int has been lifted.)


Yes, you should (or use an equivalent such as assert(p != 0) or assert(p !=
NULL) etc).

But can't we get from the Standard the following two facts:
1) any pointer can be converted (possibly with loss of information) to
an int
2) the value of such a converted pointer is 0 if and only if the pointer
was NULL

In this case all will be well - if there's a prototype in scope then the
compiler will automatically convert the pointer to an int, and 2)
guarantees that the assert behaves as intended.
 
P

pete

CJ wrote:
But can't we get from the Standard the following two facts:
1) any pointer can be converted (possibly with loss of information) to
an int

There's something like that in the standard.
Either that, or the attempt can be undefined.

N869
6.3.2.3 Pointers
[#6] Any pointer type may be converted to an integer type.
Except as previously specified, the result is
implementation-defined. If the result cannot be represented
in the integer type, the behavior is undefined. The result
need not be in the range of values of any integer type.
2) the value of such a converted pointer
is 0 if and only if the pointer was NULL

No.
There's nothing like that in the standard.

N869
6.3.2.3 Pointers
[#3] An integer constant expression with the value 0, or
such an expression cast to type void *, is called a null
pointer constant. If a null pointer constant is
converted to a pointer type, the resulting pointer, called a
null pointer, is guaranteed to compare unequal to a pointer
to any object or function.
 
K

Keith Thompson

Tomás Ó hÉilidhe said:
In C89, do we have to pass an int as an argument to assert? I've got code
at the moment that does an assertion on pointer, e.g.:

assert(p);

, but I'm wondering if I should change that to:

assert(0 != p);

Apart from the question of legality, remember that the text of the
expression is printed as part of the error message. A message
containing "p ~= NULL" is going to be much clearer than one containing
just "p" (even if you use a clear name than "p").
 
R

Richard Tobin

Keith Thompson said:
Apart from the question of legality, remember that the text of the
expression is printed as part of the error message. A message
containing "p ~= NULL" is going to be much clearer than one containing
just "p" (even if you use a clear name than "p").

While this is true, I don't think the message is of much importance.
Interpreting the output of an assertion failure is the programmer's
job, and the first thing most programmers will do is look at the
source code. Really the file and line number would be just as useful
(who has multiple assert()s on a single line?).

-- Richard
 
M

Martin Ambuhl

CJ wrote:

In this case all will be well - if there's a prototype in scope then the
compiler will automatically convert the pointer to an int, and 2)
guarantees that the assert behaves as intended.

assert is defined by the standard to be a macro. There cannot be a
prototype in scope.
 
C

Christopher Benson-Manica

[comp.lang.c] Keith Thompson said:

I would personally prefer

assert( NULL != p );

, since the error message will be somewhat more descriptive,
clarifying that p is a pointer that is NULL and not an integer that
happened to be 0.
Apart from the question of legality, remember that the text of the
expression is printed as part of the error message. A message
containing "p ~= NULL" is going to be much clearer than one containing
just "p" (even if you use a clear name than "p").

Hm, p ~= NULL sounds like a bad plan, but p != NULL might be ok :)
 
C

Christopher Benson-Manica

(WRT assert()):
While this is true, I don't think the message is of much importance.
Interpreting the output of an assertion failure is the programmer's
job, and the first thing most programmers will do is look at the
source code. Really the file and line number would be just as useful
(who has multiple assert()s on a single line?).

I initially intended to disagree with you, but given how assert is and
more or less should be used, I can't make a strong argument for
descriptive assert() messages other than mere aesthetics.
 
R

Richard Heathfield

Harald van D?k said:
The "prototype" would allow for an implicit conversion to int,

Sure, but it isn't a prototype, is it? Yes, it don't 'arf look like one,
but it's really a macro in disguise. Writing it in prototype form was,
IMO, a mistake. So no, there is no implicit conversion to int.
 
R

Richard Heathfield

Golden California Girls said:
Or perhaps rewriting it so it says something more like "Call
1-800-HELP-DESK and read us the rest of this message."

I tried this, and got "the number you have dialled has not been
recognised". Assuming we can fix that problem, some people will be using
the program in situations where they can't use the phone (either because
it's against the rules that apply in their place of work or simply because
there isn't a phone immediately to hand), so the advice doesn't work for
them.

A failing assertion indicates a broken program. The proper solution is for
your testers to have a complete list of assertions, and to arrange
white-box tests that fire those assertions if it is at all possible. If
they *can* fire the assertions, they reject the code. (And allow me to
pre-empt at least one possible response by pointing out that I'm *not*
claiming that's the *only* reason to reject code. But it is certainly one
reason.)
 
W

William Pursell

Golden California Girls said:

I tried this, and got "the number you have dialled has not been
recognised". Assuming we can fix that problem, some people will be using
the program in situations where they can't use the phone (either because
it's against the rules that apply in their place of work or simply because
there isn't a phone immediately to hand), so the advice doesn't work for
them.

Perhaps more importantly, the HELP-DESK people will likely
just tell you to reboot and hope the problem doesn't
reappear.
 
R

RoS

In data Sun, 9 Dec 2007 07:17:35 +0000 (UTC), Christopher
Benson-Manica scrisse:
[comp.lang.c] Keith Thompson said:

I would personally prefer

assert( NULL != p );

, since the error message will be somewhat more descriptive,
clarifying that p is a pointer that is NULL and not an integer that
happened to be 0.

i disagree
i cancelled all NULLs because the C[++?] compiler not compiled
some one of these (don't know why)

than i thought that with only one "0" the language were more easy;
for me exist only "0"; no NULL no '\0' no NUL
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,250
Latest member
Charlesreero

Latest Threads

Top