Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   return (i = 1, NULL) (http://www.velocityreviews.com/forums/t314922-return-i-1-null.html)

William Ahern 08-24-2003 08:35 PM

return (i = 1, NULL)
 
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

William Ahern 08-24-2003 10:39 PM

Re: return (i = 1, NULL)
 
Ben Pfaff <blp@cs.stanford.edu> 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


Jun Woong 08-25-2003 03:09 AM

Re: return (i = 1, NULL)
 

"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 (mycoboco@hanmail.net)



Samuel Barber 08-25-2003 08:02 AM

Re: return (i = 1, NULL)
 
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

Chris Spiegel 08-25-2003 09:12 AM

Re: return (i = 1, NULL)
 
On 25 Aug 2003 01:02:48 -0700, Samuel Barber <opendtv@yahoo.com> 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

Samuel Barber 08-25-2003 01:08 PM

Re: return (i = 1, NULL)
 
Chris Spiegel <usenet-20030825@happyjack.org> wrote in message news:<slrnbkjkq1.17v.wwchris@midgard.spiegels>...
> 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

William Ahern 08-26-2003 06:05 PM

Re: return (i = 1, NULL)
 
Samuel Barber <opendtv@yahoo.com> wrote:
> Chris Spiegel <usenet-20030825@happyjack.org> wrote in message news:<slrnbkjkq1.17v.wwchris@midgard.spiegels>...

<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


Ben Pfaff 08-26-2003 07:23 PM

Re: return (i = 1, NULL)
 
opendtv@yahoo.com (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

Kevin D. Quitt 08-26-2003 09:59 PM

Re: return (i = 1, NULL)
 
>> 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

William Ahern 08-26-2003 11:10 PM

Re: return (i = 1, NULL)
 
Kevin D. Quitt <KQuitt@ieeinc.com> 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.




All times are GMT. The time now is 10:16 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.