Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > return (i = 1, NULL)

Reply
Thread Tools

return (i = 1, NULL)

 
 
William Ahern
Guest
Posts: n/a
 
      08-24-2003
is this legal:

FILE *func(void) {
extern int errno;

return (errno = EINVAL, NULL);
}

my compiler (gcc 2.9.x on openbsd) is complaining that i'm returning a
pointer from int w/o a cast. gcc 3.x on linux, however, never made a peep
about it, so possibly 2.9.x is just grumpy.

i suppose the relevent question is, can one group different types like
that?

tia,

Bill
 
Reply With Quote
 
 
 
 
William Ahern
Guest
Posts: n/a
 
      08-24-2003
Ben Pfaff <(E-Mail Removed)> wrote:
> William Ahern <william@wilbur.25thandClement.com> writes:


>> is this legal:
>>
>> FILE *func(void) {
>> extern int errno;
>>
>> return (errno = EINVAL, NULL);
>> }


> No. You can't declare `errno' yourself like that (it's not
> necessarily a variable) and you forgot to #include <stdio.h>.


> If you fix those two problems, then yes.


yes. yeah.*

> If you fix those two problems, then yes.


that's what i thought. thanx.

- Bill

* - http://www.ebaumsworld.com/arnolds3.html

 
Reply With Quote
 
 
 
 
Jun Woong
Guest
Posts: n/a
 
      08-25-2003

"William Ahern" <william@wilbur.25thandClement.com> wrote in message news:36kn11-itr.ln1@wilbur.25thandClement.com...
> is this legal:
>
> FILE *func(void) {
> extern int errno;
>
> return (errno = EINVAL, NULL);
> }
>
> my compiler (gcc 2.9.x on openbsd) is complaining that i'm returning a
> pointer from int w/o a cast. gcc 3.x on linux, however, never made a peep
> about it, so possibly 2.9.x is just grumpy.
>


To avoid the discussion on the name space pollution, let me rewrite
your code:

FILE *func(void)
{
extern int my_errno;

return (my_errno = SOME_VALUE, NULL);
}

And the expression given to the return statement is not a constant
expression, becuase it contains the comma operator. Therefore, in the
*full* expression for the return, NULL doesn't qualify as a null
pointer constant. If your implementation #defines NULL simply as 0 (or
similar ones whose types are not assignment-compatible with FILE *),
your program is illegal, which is what gcc complains about.


--
Jun, Woong ((E-Mail Removed))


 
Reply With Quote
 
Samuel Barber
Guest
Posts: n/a
 
      08-25-2003
William Ahern <william@wilbur.25thandClement.com> wrote in message news:<36kn11-itr.ln1@wilbur.25thandClement.com>...
> is this legal:
>
> FILE *func(void) {
> extern int errno;
>
> return (errno = EINVAL, NULL);
> }
>
> my compiler (gcc 2.9.x on openbsd) is complaining that i'm returning a
> pointer from int w/o a cast. gcc 3.x on linux, however, never made a peep
> about it, so possibly 2.9.x is just grumpy.


Compiler bug. The return statement does not require ( ), incidentally.

Sam
 
Reply With Quote
 
Chris Spiegel
Guest
Posts: n/a
 
      08-25-2003
On 25 Aug 2003 01:02:48 -0700, Samuel Barber <(E-Mail Removed)> wrote:
> William Ahern <william@wilbur.25thandClement.com> wrote in message
> news:<36kn11-itr.ln1@wilbur.25thandClement.com>...
>> is this legal:
>>
>> FILE *func(void) {
>> extern int errno;
>>
>> return (errno = EINVAL, NULL);
>> }
>>
>> my compiler (gcc 2.9.x on openbsd) is complaining that i'm returning a
>> pointer from int w/o a cast. gcc 3.x on linux, however, never made a peep
>> about it, so possibly 2.9.x is just grumpy.

>
> Compiler bug. The return statement does not require ( ), incidentally.


It's not a compiler bug. On FreeBSD, and thus I assume OpenBSD, NULL is
an unadorned zero:
#define NULL 0

On Linux, it's
#define NULL ((void*)0)

Both are legal definitions of NULL. However, in some circumstances the
differences can bite you. This is one of those.

Since the function is defined as returning a pointer, you should return
a pointer (surprise). The issue here is what, exactly, a null pointer
is.

A plain old zero is allowed to be a null pointer, given the proper
context. One of the constraints is that it must be a constant
expression, and the comma operator is not allowed in a constant
expression.

So, assuming NULL is just zero, we have something like:
return (errno = EINVAL, 0);

The value that's being returned has type integer, and is zero. But
it's not a constant expression, and thus converting it to a pointer type
isn't going to create a null pointer (or rather, it might or might not
depending on your implementation, but it's safer to assume it won't.)

However, if NULL is ((void*)0), then it's:
return (errno = EINVAL, ((void*)0));

The value being returned here has type void*, and is a null pointer. It
is not a constant expression, but that's OK, because a constant
expression is only required to convert an integer zero to a null
pointer, not to convert a null pointer to another pointer type.

This is a very confusing part of C, but it does show why you should
always pretend NULL is just a plain old zero. In fact, some people
refuse to use NULL at all because of issues like this; instead, they
just use a zero as a null pointer. I like NULL, personally, because I
know when to cast it and using NULL just makes the code a bit more self
documenting, IMO.

To be complete, the proper fix for the above code is:
return (errno = EINVAL, (void*)NULL);
or
return (errno = EINVAL, (void*)0);
or
... something that doesn't use the comma operator!

Chris
 
Reply With Quote
 
Samuel Barber
Guest
Posts: n/a
 
      08-25-2003
Chris Spiegel <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> A plain old zero is allowed to be a null pointer, given the proper
> context. One of the constraints is that it must be a constant
> expression, and the comma operator is not allowed in a constant
> expression.
>
> So, assuming NULL is just zero, we have something like:
> return (errno = EINVAL, 0);
>
> The value that's being returned has type integer, and is zero. But
> it's not a constant expression, and thus converting it to a pointer type
> isn't going to create a null pointer (or rather, it might or might not
> depending on your implementation, but it's safer to assume it won't.)
>
> However, if NULL is ((void*)0), then it's:
> return (errno = EINVAL, ((void*)0));
>
> The value being returned here has type void*, and is a null pointer. It
> is not a constant expression, but that's OK, because a constant
> expression is only required to convert an integer zero to a null
> pointer, not to convert a null pointer to another pointer type.


Thank you for the correction.

> To be complete, the proper fix for the above code is:
> return (errno = EINVAL, (void*)NULL);
> or
> return (errno = EINVAL, (void*)0);
> or
> .. something that doesn't use the comma operator!


The last is by far the best fix, most importantly because (void*)0 is
not portable to C++.

Sam
 
Reply With Quote
 
William Ahern
Guest
Posts: n/a
 
      08-26-2003
Samuel Barber <(E-Mail Removed)> wrote:
> Chris Spiegel <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...

<snip>
>> To be complete, the proper fix for the above code is:
>> return (errno = EINVAL, (void*)NULL);
>> or
>> return (errno = EINVAL, (void*)0);
>> or
>> .. something that doesn't use the comma operator!

>
> The last is by far the best fix, most importantly because (void*)0 is
> not portable to C++.
>
> Sam


I liked the comma form because of its expressiveness. I've used it
exclusively w/ setting errno in a bunch of code (tho, this was the only
instance where I was returning a pointer rather than an int). In these cases
you really are returning two values, and it makes the code much more
readable w/o the additional braces since I love to do a lot of sanity
checking (since I never know where I might copy+paste the code).

But, I'll be mindful of the pitfalls. Thanks Chris for the great
explanation.

- Bill

 
Reply With Quote
 
Ben Pfaff
Guest
Posts: n/a
 
      08-26-2003
http://www.velocityreviews.com/forums/(E-Mail Removed) (Samuel Barber) writes:

> The last is by far the best fix, most importantly because (void*)0 is
> not portable to C++.


When writing C code, there is no reason to worry about what C++
compilers will think of it. (Header files are a possible
exception.)
--
"The expression isn't unclear *at all* and only an expert could actually
have doubts about it"
--Dan Pop
 
Reply With Quote
 
Kevin D. Quitt
Guest
Posts: n/a
 
      08-26-2003
>> return (my_errno = SOME_VALUE, NULL);


Why not:

my_errno = SOME_VALUE; return NULL;

--
#include <standard.disclaimer>
_
Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
Per the FCA, this address may not be added to any commercial mail list
 
Reply With Quote
 
William Ahern
Guest
Posts: n/a
 
      08-26-2003
Kevin D. Quitt <(E-Mail Removed)> wrote:
>>> return (my_errno = SOME_VALUE, NULL);

>
>
> Why not:
>
> my_errno = SOME_VALUE; return NULL;


Because I usually use brevity and clarity like so:

if (check_parameter)
return (errno = EINVAL, NULL);

Tho, this was the first time I had to return a null pointer rather
than another error identifer like -1.

The alterntives are:

if (some_condition) {
errno = EINVAL;
return NULL;
}

[three or four more time]

or

if (some_condition1 || some_condition2 || some_condition3 || ...) {
errno = (some_condition)? ENAMETOOLONG : EINVAL
return NULL;
}

Neither of those are very satisfactory for code that isn't even central
to the purpose of the function.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
what value does lack of return or empty "return;" return Greenhorn C Programming 15 03-06-2005 08:19 PM
difference between return &*i and return i; Ganesh Gella C++ 4 11-12-2004 04:28 PM
getting return value from function without return statement. Seong-Kook Shin C Programming 1 06-18-2004 08:19 AM
How do I return a return-code from main? wl Java 2 03-05-2004 05:15 PM
Return a return value from Perl to Javascript PvdK Perl 0 07-24-2003 09:20 AM



Advertisments