null function pointer?

  • Thread starter Alexei A. Frounze
  • Start date
A

Alexei A. Frounze

Seems like, to make sure that a pointer doesn't point to an object/function,
NULL (or simply 0) is good enough for both kind of pointers, data pointers
and function pointers as per 6.3.2.3:

3 An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
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.

4 Conversion of a null pointer to another pointer type yields a null pointer
of that type.
Any two null pointers shall compare equal.

It's a stupid question, but how about comparing data to function pointers?
Null function pointer should compare equal to null data pointer, right,
wrong? Doesn't different bit representation of the pointers make problems
here or are they solved through casting or is this not really
specified/defined?

Alex
 
G

Gordon Burditt

3 An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
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.

4 Conversion of a null pointer to another pointer type yields a null pointer
of that type.
Any two null pointers shall compare equal.

It's a stupid question, but how about comparing data to function pointers?

data pointers and function pointers are often of different sizes.
For example, "middle" and "compact" memory models on i386 in 16-bit
mode. (one has 16-bit data pointers and 32-bit function pointers,
the other has the reverse).
Null function pointer should compare equal to null data pointer, right,
wrong?

I don't think you should do such a comparison. It makes almost
(but not quite) as much sense as comparing a null pointer to
a struct (NOT struct pointer, struct).
Doesn't different bit representation of the pointers make problems
here or are they solved through casting or is this not really
specified/defined?

The whole operation doesn't make any sense, particularly when neither
pointer is null. Deletion of the program would be the best defined
behavior to establish.

Gordon L. Burditt
 
S

Skarmander

Alexei said:
Seems like, to make sure that a pointer doesn't point to an object/function,
NULL (or simply 0) is good enough for both kind of pointers, data pointers
and function pointers as per 6.3.2.3:

3 An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
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.

4 Conversion of a null pointer to another pointer type yields a null pointer
of that type.
Any two null pointers shall compare equal.

It's a stupid question, but how about comparing data to function pointers?
Null function pointer should compare equal to null data pointer, right,
wrong? Doesn't different bit representation of the pointers make problems
here or are they solved through casting or is this not really
specified/defined?
What are you asking? Whether

if ((char*) 0 == (char*) (void (*)()) 0) {
S
} else {
T
}

should always execute S?

Who cares? :)

S.
 
A

Alexei A. Frounze

Gordon Burditt said:
pointers?

data pointers and function pointers are often of different sizes.
For example, "middle" and "compact" memory models on i386 in 16-bit
mode. (one has 16-bit data pointers and 32-bit function pointers,
the other has the reverse).

Right, and I know that.
I don't think you should do such a comparison. It makes almost
(but not quite) as much sense as comparing a null pointer to
a struct (NOT struct pointer, struct).


The whole operation doesn't make any sense, particularly when neither
pointer is null. Deletion of the program would be the best defined
behavior to establish.

I know, that's why I wrote "*stupid* question" :) It's as stupid as writing
"SLIPPERY WHEN WET" on the bank near the water.
But still both void*p=NULL and void (f*)()=NULL are null pointers as per the
standard and as per the standard such pointers should compare equal... Can
they compare equal when one of them isn't a null pointer? I'm just curious.
Or am I asking too much from the standard? :)

Alex
 
A

Alexei A. Frounze

....
What are you asking? Whether

if ((char*) 0 == (char*) (void (*)()) 0) {
S
} else {
T
}

should always execute S?

Exactly. :)
Who cares? :)

The curious me. I wouldn't write such code in the first place, but the
curiousity... :)

Alex
 
M

Mike Wahler

Alexei A. Frounze said:
But still both void*p=NULL and void (f*)()=NULL are null pointers as per
the
standard and as per the standard such pointers should compare equal... Can
they compare equal when one of them isn't a null pointer?

Think about what you've asked:

if A == B then does !A == B or !B == A ?

I'm just curious.
Or am I asking too much from the standard? :)

You seem to be asking if logic is logical or not. :)

-Mike
 
M

Michael Mair

Alexei said:
Seems like, to make sure that a pointer doesn't point to an object/function,
NULL (or simply 0) is good enough for both kind of pointers, data pointers
and function pointers as per 6.3.2.3:

3 An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
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.

4 Conversion of a null pointer to another pointer type yields a null pointer
of that type.
Any two null pointers shall compare equal.

It's a stupid question, but how about comparing data to function pointers?
Null function pointer should compare equal to null data pointer, right,
wrong? Doesn't different bit representation of the pointers make problems
here or are they solved through casting or is this not really
specified/defined?

I guess the only thing that should be enabled by that is that
myfunptr == NULL
makes sense, even if NULL is defined as (void *)0. Apart from
that, the comparison of data and function pointers is a Bad Idea
but you already know this :)


Cheers
Michael
 
A

Anonymous 7843

if ((char*) 0 == (char*) (void (*)()) 0) {
S
} else {
T
}

should always execute S?

Who cares? :)

The unprototyped function pointer seems a greater sin to me.
I mean, the last thing you want is a mismatched argument
in your call to the NULL function...
 
K

Keith Thompson

Alexei A. Frounze said:
Seems like, to make sure that a pointer doesn't point to an object/function,
NULL (or simply 0) is good enough for both kind of pointers, data pointers
and function pointers as per 6.3.2.3:

3 An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
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.

4 Conversion of a null pointer to another pointer type yields a null pointer
of that type.
Any two null pointers shall compare equal.

It's a stupid question, but how about comparing data to function pointers?
Null function pointer should compare equal to null data pointer, right,
wrong? Doesn't different bit representation of the pointers make problems
here or are they solved through casting or is this not really
specified/defined?

I think that "Any two null pointers shall compare equal" is intended
to refer only to pointers that *can* be compared. (And I think the
wording is slightly sloppy.)

You can convert a null pointer constant to either a pointer-to-object
type or to a pointer-to-function type (because the standard
specifically says so). There is no conversion, explicit or implicit,
defined between object pointers and function pointers (though some
implementations might allow such conversions as an extension).

So, given

int *obj_ptr = NULL;
void (*func_ptr)(void) = NULL;

the following expression:

obj_ptr == func_ptr

is a constraint violation, because the types are incompatible. Even
casting one argument to the other's type won't help, because no
conversion is defined.

(Arguments that the comparison doesn't make sense don't really answer
the question. C allows plenty of things that don't make sense. The
relevant point here is that this happens not to be one of them.)
 
E

Eric Sosman

Alexei A. Frounze wrote On 10/07/05 16:44,:
Seems like, to make sure that a pointer doesn't point to an object/function,
NULL (or simply 0) is good enough for both kind of pointers, data pointers
and function pointers as per 6.3.2.3:

3 An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.55)
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.

4 Conversion of a null pointer to another pointer type yields a null pointer
of that type.
Any two null pointers shall compare equal.

It's a stupid question, but how about comparing data to function pointers?
Null function pointer should compare equal to null data pointer, right,
wrong? Doesn't different bit representation of the pointers make problems
here or are they solved through casting or is this not really
specified/defined?

6.5.9 says of the == and != operators

One of the following shall hold:
-- both operands have arithmetic type;
-- both operands are pointers to qualified or
unqualified versions of compatible types;
-- one operand is a pointer to an object or
incomplete type and the other is a pointer to
a qualified or unqualified version of void; or
-- one operand is a pointer and the other is a
null pointer constant.

The comparison doesn't satisfy any of these constraints,
so a "shall" has been violated and a diagnostic is required.

Thus we can learn that `dataPtr == NULL' is true and
that `funcPtr == NULL' is true, but it is not permitted even
to ask whether `dataPtr == funcPtr'.

The constraints of 6.5.9 seem to contradict the language
in 6.3.2.3; perhaps a query on comp.std.c is in order ...
 
A

Alexei A. Frounze

Keith Thompson said:
I think that "Any two null pointers shall compare equal" is intended
to refer only to pointers that *can* be compared. (And I think the
wording is slightly sloppy.) ....
So, given

int *obj_ptr = NULL;
void (*func_ptr)(void) = NULL;

the following expression:

obj_ptr == func_ptr

is a constraint violation, because the types are incompatible. Even
casting one argument to the other's type won't help, because no
conversion is defined.

(Arguments that the comparison doesn't make sense don't really answer
the question. C allows plenty of things that don't make sense. The
relevant point here is that this happens not to be one of them.)

OK then, the "wording being slightly sloppy" answers to my question better.
And yes, there's always enough rope in C to shoot in the foot. :)

Alex
 
T

Tim Rentsch

Keith Thompson said:
There is no conversion, explicit or implicit,
defined between object pointers and function pointers

Technically not quite correct. The code

int (*pf)(void);

pf = (void*)0;

converts an object pointer value to a function pointer. It's true,
the object pointer expression in this case is also a null pointer
constant, but the expression still yields a value of object pointer
type, and that value is converted by the assignment. (It could also
be converted by casting, eg, 'pf = (int (*)(void))(void*)0'.)
 
P

pete

Tim said:
Technically not quite correct. The code

int (*pf)(void);

pf = (void*)0;

converts an object pointer value to a function pointer.
It's true, the object pointer expression in this
case is also a null pointer constant,
but the expression still yields a value of object pointer type,
and that value is converted by the assignment.

No.
(void *) is a pointer to an incomplete type,
not a pointer to an object type.
 
T

Tim Rentsch

pete said:
No.
(void *) is a pointer to an incomplete type,
not a pointer to an object type.

Sorry, I was using the term informally. The posting I was
responding to (which apparently I snipped too much of),
mentioned only object pointers and function pointers, which
I took to mean pointers to non-function types and to
function types, and that's how the terms were meant to be
taken in my posting. So if Keith meant something different
than what it seemed like he was saying, I withdraw my
followup comment.
 
C

Chris Torek

No.
(void *) is a pointer to an incomplete type,
not a pointer to an object type.

Indeed, although "pointer to incomplete [data] type" could be
considered a sub-group of "pointer to object type", or more
generically, "data pointer" -- to be distinguished from "function
pointer", a la Harvard architectures in general.

More important, I think, is that (as Tim Rentsch himself noted)
(void *)0 is not only "the null pointer of type (void *)", it is
also "ankhpee" (ANCP, A Null Pointer Constant). If its "ankhpee-ness"
is considered to override its "null pointer of type void-*"-ness
in this particular case, the problem itself (of mixing "data pointer"
and "function pointer") goes away.

I think this is much clearer in Sea, the C-like language that is
virtually 100% identical to ANSI C, except for two things:

- Neither 0 nor (void *)0 are ever "a null pointer constant".
The code fragment:

int *p = 0;

is valid C, but an error in Sea.

- In Sea, the null pointer constant can only be spelled "nil",
which is a keyword:

int *p = nil;

sets p such that it is valid, but does not point to anything.

(Note that in Sea, the call:

extern void varfunc(char *, ...);

varfunc("hello", "world", nil);

draws a compile-time diagnostic, because the compiler is missing
the type information required to turn "nil" into an appropriate
null pointer. You must insert a cast to supply the correct type
here.)

In Sea, if we write:

void (*fp)(void) = nil;

it compile just fine -- nil itself is untyped, but produces a "null
function pointer" in the same way it produces a "null data pointer":
a pointer that is valid, but compares unequal to all actual functions
(so "fp != somevoidfunc" is always true).

Because Sea's <stdio.h> et al contain "#define NULL nil", any
well-written C program is a valid Sea program, provided the C
program avoids using the "nil" keyword. Any programmer proficient
in C is also proficient in Sea. The only real difference is that
Sea catches some errors that are common in C. :)

(One of these days I should hack up gcc a bit and produce gcsea.)
 
C

Chris Torek

(void *)0 is not only "the null pointer of type (void *)", it is
also "ankhpee" (ANCP, A Null Pointer Constant).

Of course, this should be ANPC (which implies a different
pronunciation, maybe "an-pee-cee").
 
P

pete

Chris said:
No.
(void *) is a pointer to an incomplete type,
not a pointer to an object type.

Indeed, although "pointer to incomplete [data] type" could be
considered a sub-group of "pointer to object type", or more
generically, "data pointer" -- to be distinguished from "function
pointer", a la Harvard architectures in general.

No.
In C, there's three kinds of types:
1 object
2 incomplete
3 function

What Keith Thompson wrote is just simply and completely
accurate and useful to know, as far as C is concerned.
 
T

Tim Rentsch

pete said:
Chris said:
There is no conversion, explicit or implicit,
defined between object pointers and function pointers
Tim Rentsch wrote:
Technically not quite correct. The code

int (*pf)(void);

pf = (void*)0;

converts an object pointer value to a function pointer.
It's true, the object pointer expression in this
case is also a null pointer constant,
but the expression still yields a value of object pointer type,
and that value is converted by the assignment.

No.
(void *) is a pointer to an incomplete type,
not a pointer to an object type.

Indeed, although "pointer to incomplete [data] type" could be
considered a sub-group of "pointer to object type", or more
generically, "data pointer" -- to be distinguished from "function
pointer", a la Harvard architectures in general.

No.
In C, there's three kinds of types:
1 object
2 incomplete
3 function

What Keith Thompson wrote is just simply and completely
accurate and useful to know, as far as C is concerned.

1. That presumes it's possible to assign only one meaning to what
Keith wrote.

2. It's common usage in ordinary discussions for "object pointer" to
mean a pointer to an object type or to an incomplete type. (Not
the only usage, but one common usage.) To pretend otherwise is,
well, pretending.


I don't know which interpretation Keith intended, but certainly
more than one interpretation is possible.
 
K

Keith Thompson

Tim Rentsch said:
1. That presumes it's possible to assign only one meaning to what
Keith wrote.

2. It's common usage in ordinary discussions for "object pointer" to
mean a pointer to an object type or to an incomplete type. (Not
the only usage, but one common usage.) To pretend otherwise is,
well, pretending.


I don't know which interpretation Keith intended,

I'm not entirely sure of that myself. Actually, I just hadn't thought
about the void* case.
but certainly
more than one interpretation is possible.

C99 6.2.5p20 says:

A _pointer type_ may be derived from a function type, an object
type, or an incomplete type, called the _referenced type_.

which seems to imply three different classes of pointers. On the
other hand, 7.18.1.4 is titled "Integer types capable of holding
object pointers", but it talks only about pointers to void (which
themselves, of course can hold the values of any object pointers).

In any case, the conversion from void* to a function pointer type
occurs *only* for null pointer constants. It's a special case, which
is why I didn't think of it.
 
P

pete

Tim said:
pete said:
Chris said:
There is no conversion, explicit or implicit,
defined between object pointers and function pointers

Tim Rentsch wrote:
Technically not quite correct. The code

int (*pf)(void);

pf = (void*)0;

converts an object pointer value to a function pointer.
It's true, the object pointer expression in this
case is also a null pointer constant,
but the expression still yields a value of object pointer type,
and that value is converted by the assignment.

No.
(void *) is a pointer to an incomplete type,
not a pointer to an object type.

Indeed, although "pointer to incomplete [data] type" could be
considered a sub-group of "pointer to object type", or more
generically, "data pointer" -- to be distinguished from "function
pointer", a la Harvard architectures in general.

No.
In C, there's three kinds of types:
1 object
2 incomplete
3 function

What Keith Thompson wrote is just simply and completely
accurate and useful to know, as far as C is concerned.

1. That presumes it's possible to assign only one meaning to what
Keith wrote.

2. It's common usage in ordinary discussions for "object pointer" to
mean a pointer to an object type or to an incomplete type. (Not
the only usage, but one common usage.) To pretend otherwise is,
well, pretending.

I'm not agreeing.
I don't know which interpretation Keith intended, but certainly
more than one interpretation is possible.

The more obvious interpretation is that there's no definition
for conversions between object addresses and function addresses.

I don't see any point in contradicting his statement.

As well as not pointing to any object type
(void *)0 doesn't point to any object.
"object pointer" doesn't describe (void *)0
any better than "function pointer" does.

Tthe relationship between
(void *)0 and pointers to object types,
is exactly the same as the relationship between
(void *)0 and pointers to function types.

There's no special relationship between (void *)0
concerning objects versus functions.
null pointers are of both pointer to object types
and pointer to function types.

(void *) is as much of a function pointer
as it is an object pointer,
that is to say "it isn't either".
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top