Is a "cast" ever necessary in "return"?

L

LaEisem

On-the-job, I have "inherited" a lot of old C language software.
A question or two about when "casting" of null pointer constants
is [not] needed has occurred during behind-the-scenes cleanup
of some of that software. That subject seems not to be addressed,
at least not directly, in the C FAQ where FAQ 5.2 seems most relevant.

References:
* C FAQ 5.2 Null pointers
(Including conditions where "casting" of
null pointer constants is (not) needed)
* ANSI C Standard 6.2.2.3 Pointers
(Including null pointer constant)
* ANSI C Standard 6.6.6.4 The return statement
* ANSI C Standard 7.1.6 (Including NULL macro which expands to
a null pointer constant)

Is it ever necessary to "cast", in a "return" statement, a NULL
(or an "unadorned 0", to use terminology from C FAQ 5.2)
that appears as the to-be-returned value in that "return" statement?
Does it matter whether or not a function prototype is in scope
for the function in which such a "return" statement appears?

Example: If the "return" statement below appeared in a C function,
would the "(char *)" cast ever be necessary?
return (char *)NULL;

Does the return of NULL or of an "unadorned 0" in a "return" statement
constitute an "assignment context", as that term is used in C FAQ 5.2?
In general, does the return of an arbitrary value in a "return"
statement constitute such an "assignment context"?
If it did, would that not be a problem if an unadorned 0 (not NULL)
was to be returned in a "return" statement with the intent that it be
interpreted as an integer 0 rather than as a (null) pointer?

Much thanks...
 
P

Peter Pichler

LaEisem said:
Is it ever necessary to "cast", in a "return" statement, a NULL
(or an "unadorned 0", to use terminology from C FAQ 5.2)
that appears as the to-be-returned value in that "return" statement?
Does it matter whether or not a function prototype is in scope
for the function in which such a "return" statement appears?

Example: If the "return" statement below appeared in a C function,
would the "(char *)" cast ever be necessary?
return (char *)NULL;

Does the return of NULL or of an "unadorned 0" in a "return" statement
constitute an "assignment context", as that term is used in C FAQ 5.2?
In general, does the return of an arbitrary value in a "return"
statement constitute such an "assignment context"?

Try answering this yourself: what if the function returned, for example,
a double and you used 'return 42;'? What would get returned? Why would
be returning NULL (or 0, for that matter) different?
If it did, would that not be a problem if an unadorned 0 (not NULL)
was to be returned in a "return" statement with the intent that it be
interpreted as an integer 0 rather than as a (null) pointer?

NULL is on many platforms #defined as 0.

Peter
 
I

Irrwahn Grausewitz

(e-mail address removed) (LaEisem) wrote:

Is it ever necessary to "cast", in a "return" statement, a NULL
(or an "unadorned 0", to use terminology from C FAQ 5.2)
that appears as the to-be-returned value in that "return" statement?
Does it matter whether or not a function prototype is in scope
for the function in which such a "return" statement appears?

As a function definition is also a proper function prototype there is
no way to define a function returning a pointer without a prototype in
scope.
Example: If the "return" statement below appeared in a C function,
would the "(char *)" cast ever be necessary?
return (char *)NULL;

If the function is defined to return a pointer to char the cast is
spurious. Otherwise the cast makes no sense. Just drop it.
Does the return of NULL or of an "unadorned 0" in a "return" statement
constitute an "assignment context", as that term is used in C FAQ 5.2?
In general, does the return of an arbitrary value in a "return"
statement constitute such an "assignment context"?

Generally, yes.
If it did, would that not be a problem if an unadorned 0 (not NULL)
was to be returned in a "return" statement with the intent that it be
interpreted as an integer 0 rather than as a (null) pointer?

Any integer constant resolving to 0 or such a constant casted to void*
serves as a proper null pointer constant. Thus it will automatically be
casted to the pointer type in question on assignment. NULL and 0 are
interchangeable in pointer contexts (with the exceptions mentioned in
FAQ 5.2, but you already know this).

HTH
Regards
 
J

Jeremy Yallop

Irrwahn said:
As a function definition is also a proper function prototype there is
no way to define a function returning a pointer without a prototype in
scope.

Not all function definitions are prototypes. The following is a
definition but not a prototype:

int *f() { return 0; }

Jeremy.
 
S

Sheldon Simms

Is it ever necessary to "cast", in a "return" statement, a NULL
(or an "unadorned 0", to use terminology from C FAQ 5.2)
that appears as the to-be-returned value in that "return" statement?
Does it matter whether or not a function prototype is in scope
for the function in which such a "return" statement appears?

I think this is pretty clearly explained in 6.8.6.4:

#3 If a return statement with an expression is executed, the
value of the expression is returned to the caller as the value
of the function call expression. If the expression has a type
different from the return type of the function in which it
appears, the value is converted as if by assignment to an
object having the return type of the function.

A function prototype isn't necessary to determine the return
type of the function because the return statement is *in* the
function definition and the return type is known.

As long as a function is declared to return any pointer type,
there is no need to cast the null pointer constant 0 or the
macro NULL in a return statement. The only case in which you
might need to cast either of the above would in really ancient
code that intends to return a pointer value from a function
declared without a return type at all. In that case, the return
type would be recognized as int, and the cast would be
necessary -- but the code still wouldn't be correct, because
there is no guarantee that a null pointer can be converted to
an int (and presumably back to a pointer) without changing
its value.

Since such function declarations are not even legal C anymore
anyway, the fix would be to change the function declarations
to use an explicit return type.

-Sheldon
 
D

Dan Pop

In said:
As long as a function is declared to return any pointer type,
there is no need to cast the null pointer constant 0 or the
macro NULL in a return statement. The only case in which you
might need to cast either of the above would in really ancient
code that intends to return a pointer value from a function
declared without a return type at all. In that case, the return
type would be recognized as int, and the cast would be
necessary

If you put the cast, the compiler *must* emit a diagnostic, because it
has to convert the pointer back to int, and this requires an *explicit*
cast from pointer to int.
-- but the code still wouldn't be correct, because
there is no guarantee that a null pointer can be converted to
an int (and presumably back to a pointer) without changing
its value.

The code may not compile at all, given that it requires a diagnostic.
Since such function declarations are not even legal C anymore
anyway, the fix would be to change the function declarations
to use an explicit return type.

Such functions are in *no* way different from functions explicitly
defined as returning int (in both C89 and pre-ANSI C). So, I can't
understand why you think that they are somehow a special case in the
context of this discussion. They aren't: a function defined as returning
int is a function defined as returning int, whether the definition was
explicit or implicit.

Dan
 
I

Irrwahn Grausewitz

Jeremy Yallop said:
Not all function definitions are prototypes. The following is a
definition but not a prototype:

int *f() { return 0; }

Doh! You're right. But I think my point holds that you cannot
(portably) define a function returning a pointer without, err...
defining that function to return a pointer.

Regards
 
T

Thomas Stegen

Irrwahn said:
Doh! You're right. But I think my point holds that you cannot
(portably) define a function returning a pointer without, err...
defining that function to return a pointer.

Just as you can't eat a banana without eating a banana.
 
S

Sheldon Simms

Such functions are in *no* way different from functions explicitly
defined as returning int (in both C89 and pre-ANSI C). So, I can't
understand why you think that they are somehow a special case in the
context of this discussion.

I didn't, I was thinking that it is possible that some beginners
might not know that the return value is (implicitly) int when
confronted with such a function - especially if the function
body contains something like "return (char *)NULL;"

-Sheldon
 
I

Irrwahn Grausewitz

Thomas Stegen said:
Irrwahn said:
[...] you cannot
(portably) define a function returning a pointer without, err...
defining that function to return a pointer.

Just as you can't eat a banana without eating a banana.

Exactely.
 
J

j

Jeremy Yallop said:
Not all function definitions are prototypes. The following is a
definition but not a prototype:

int *f() { return 0; }

And it is also considered obsolescent.
 

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,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top