[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Changing the return type of a function from void to int

C++Liliput

5/9/2011 4:38:00 PM

Hi,
I have a set of APIs that currently have a void return type. I want
to change this to int because I am wrapping around these APIs in JNI
and want to throw exceptions under certain error conditions. Since
that is possible only if I return an int (that denotes an error
condition), my question is this - does changing the return type of a
function from void to int break any backward compatibility with the
older clients of the API? It doesn't look like it since the older
clients can continue to use the new APIs in the void context. Are
there any other pitfalls to this change?

Thanks
Aveek
15 Answers

Shao Miller

5/9/2011 5:18:00 PM

0

On 5/9/2011 11:37 AM, C++Liliput wrote:
> I have a set of APIs that currently have a void return type. I want
> to change this to int...
> ...
> ...my question is this - does changing the return type of a
> function from void to int break any backward compatibility with the
> older clients of the API?

Do you mean if the older clients are recompiled to use modified headers?
Or do you mean that the older clients remain the way they are but will
be calling into a modified library where these functions now return
'int' instead of 'void'?

For the latter, I might be worried a bit about n1256.pdf's 6.5.2.2p9.
The older clients would be calling the functions using a function type
other than how the functions are defined in the newly-compiled library.
If that results in undefined behaviour, and outside of the scope of C,
if a stack is used to return function values, and if the caller is
expected to clean up that stack after a function call, the older clients
would not be cleaning very well by assuming a 'void' return type.

Or maybe I'm wrong and in:

typedef void f_ret_void(int);
typedef int f_ret_int(int);

the types 'f_ret_void' and 'f_ret_int' are compatible. That doesn't
seem quite right, though. :)

Perhaps this is a non-issue in your environment, though. Does the
product/do the products need to be utterly portable in a standard sense?

Keith Thompson

5/9/2011 5:19:00 PM

0

"C++Liliput" <aveekmisra@gmail.com> writes:
> I have a set of APIs that currently have a void return type. I want
> to change this to int because I am wrapping around these APIs in JNI
> and want to throw exceptions under certain error conditions. Since
> that is possible only if I return an int (that denotes an error
> condition), my question is this - does changing the return type of a
> function from void to int break any backward compatibility with the
> older clients of the API? It doesn't look like it since the older
> clients can continue to use the new APIs in the void context. Are
> there any other pitfalls to this change?

As far as the C language is concerned, a function returning int is
simply incompatible with a function returning void, and the behavior of
a program that calls one such function as if it were the other is
undefined.

It may be that you can get away with it on your platform, but that's a
question about your platform, not about C.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Fred

5/9/2011 6:14:00 PM

0

On May 9, 10:19 am, Keith Thompson <ks...@mib.org> wrote:
> "C++Liliput" <aveekmi...@gmail.com> writes:
> >   I have a set of APIs that currently have a void return type. I want
> > to change this to int because I am wrapping around these APIs in JNI
> > and want to throw exceptions under certain error conditions. Since
> > that is possible only if I return an int (that denotes an error
> > condition), my question is this - does changing the return type of a
> > function from void to int break any backward compatibility with the
> > older clients of the API? It doesn't look like it since the older
> > clients can continue to use the new APIs in the void context. Are
> > there any other pitfalls to this change?
>
> As far as the C language is concerned, a function returning int is
> simply incompatible with a function returning void, and the behavior of
> a program that calls one such function as if it were the other is
> undefined.
>

So you are saying that the statement
printf( "Hello, World!\n" );
provokes undefined behavior, since I am calling it
as if it were a function returning void rather than
int n;
n = printf( "Hello, World!\n" );
where I am calling it as a function returning an int?
--
Fred K

Keith Thompson

5/9/2011 6:27:00 PM

0

Fred <fred.l.kleinschmidt@boeing.com> writes:
> On May 9, 10:19 am, Keith Thompson <ks...@mib.org> wrote:
>> "C++Liliput" <aveekmi...@gmail.com> writes:
>> >   I have a set of APIs that currently have a void return type. I want
>> > to change this to int because I am wrapping around these APIs in JNI
>> > and want to throw exceptions under certain error conditions. Since
>> > that is possible only if I return an int (that denotes an error
>> > condition), my question is this - does changing the return type of a
>> > function from void to int break any backward compatibility with the
>> > older clients of the API? It doesn't look like it since the older
>> > clients can continue to use the new APIs in the void context. Are
>> > there any other pitfalls to this change?
>>
>> As far as the C language is concerned, a function returning int is
>> simply incompatible with a function returning void, and the behavior of
>> a program that calls one such function as if it were the other is
>> undefined.
>>
>
> So you are saying that the statement
> printf( "Hello, World!\n" );
> provokes undefined behavior, since I am calling it
> as if it were a function returning void rather than
> int n;
> n = printf( "Hello, World!\n" );
> where I am calling it as a function returning an int?

No, not at all.

If you have the required #include <stdio.h>, then the correct
declaration of printf (returning int) is visible to the compiler
when it compiles the call. It generates code that calls printf()
with the specified arguments, then discards the result.

On the other hand, if you omit the #include, and instead try to
declare printf yourself as a void function, then the behavior
is undefined:

extern void printf(const char *format, ...);

int main(void)
{
printf("Hello, World!\n");
return 0;
}

And if you omit the declaration altogether, then a C90 compiler
will implicitly assume that the unknown function "printf" returns
int -- but it will also assume that it takes a fixed number of
arguments based on the call, whereas printf is actually variadic.
Since fixed-argument and variadic functions can use different calling
conventions, again, the behavior is undefined. In C99, calling a
function without a visible declaration is a constraint violation;
if the compiler chooses to generate an executable after issuing
a warning, again, the language doesn't define the behavior of the
resulting program. A sufficiently clever compiler might recognize
the name "printf" and warn you that you're doing something wrong,
but that's not required.

It's common for funtions returning int and functions returning void
to be "compatible" in practice. For example, an int function might
store its result in a specified CPU register; calling it as if it
were a void function merely ignores whatever is in that register.
But other calling schemes are possible.

Basically, if you lie to the compiler, all bets are off.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Shao Miller

5/9/2011 6:44:00 PM

0

On 5/9/2011 1:14 PM, Fred wrote:
> On May 9, 10:19 am, Keith Thompson<ks...@mib.org> wrote:
>> As far as the C language is concerned, a function returning int is
>> simply incompatible with a function returning void, and the behavior of
>> a program that calls one such function as if it were the other is
>> undefined.
>>
>
> So you are saying that the statement
> printf( "Hello, World!\n" );
> provokes undefined behavior, since I am calling it
> as if it were a function returning void rather than
> int n;
> n = printf( "Hello, World!\n" );
> where I am calling it as a function returning an int?

I don't think he's saying that.

I believe that the expression for the called function, 'printf' in this
instance, is the same regardless of what you are doing with the result
of the function call. And in your former case, I think that you simply
have a "void expression," which is evaluated.

The same as:

int n = 3;
n;

You might chop it up thusly:

[ [ [printf] [ [(] ["Hello, world!\n"] [)] ] ] [;] ]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

and:

[ [ [n] [=] [ [printf] [ [(] ["Hello, world!\n"] [)] ] ] ] [;] ]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The "outer" expression for the assignment of 'n' should not influence
the "inner" expression for the function call; that expression is a
sub-expression in its own right, if I understand correctly. :)

Keith Thompson

5/9/2011 6:51:00 PM

0

Shao Miller <sha0.miller@gmail.com> writes:
> On 5/9/2011 1:14 PM, Fred wrote:
>> On May 9, 10:19 am, Keith Thompson<ks...@mib.org> wrote:
>>> As far as the C language is concerned, a function returning int is
>>> simply incompatible with a function returning void, and the behavior of
>>> a program that calls one such function as if it were the other is
>>> undefined.
>>>
>>
>> So you are saying that the statement
>> printf( "Hello, World!\n" );
>> provokes undefined behavior, since I am calling it
>> as if it were a function returning void rather than
>> int n;
>> n = printf( "Hello, World!\n" );
>> where I am calling it as a function returning an int?
>
> I don't think he's saying that.
>
> I believe that the expression for the called function, 'printf' in this
> instance, is the same regardless of what you are doing with the result
> of the function call. And in your former case, I think that you simply
> have a "void expression," which is evaluated.
[...]

Not quite. A void expression would be an expression whose type is void.
There is no void expression in the statement
printf( "Hello, World!\n" );

[consulting the standard]

Hang on, maybe there is. C99 6.8.3 describes statement expressions (an
expression with a semicolon added to the end of it can be used as a
statement). The semantics are:

The expression in an expression statement is evaluated as a void
expression for its side effects.

Frankly, I find that wording a bit misleading. I would have said that
the expression is evaluated for its side effects, and any result is
discarded.

Given the current wording, I suppose one could argue that evaluating a
printf call "as a void expression" means calling printf *as if* it
returned void, and therefore the behavior is undefined. But I'm certain
that that's not the intent, since it would break most C programs.

Looks like another question for comp.std.c.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Shao Miller

5/9/2011 7:07:00 PM

0

On 5/9/2011 1:51 PM, Keith Thompson wrote:
....C99 6.8.3 describes statement expressions (an
> expression with a semicolon added to the end of it can be used as a
> statement). The semantics are:
>
> The expression in an expression statement is evaluated as a void
> expression for its side effects.
>
> ...
>
> Given the current wording, I suppose one could argue that evaluating a
> printf call "as a void expression" means calling printf *as if* it
> returned void, and therefore the behavior is undefined. But I'm certain
> that that's not the intent, since it would break most C programs.
>
> Looks like another question for comp.std.c.
>

I'm certain of the same, but not so certain one could argue that
argument. Since the outermost expression is a function call, and that
expression has a result type, then I think 6.3.2.2p1 would allow for the
value to be discarded just as you suggest it ought.

Martin Ambuhl

5/9/2011 7:10:00 PM

0

On 5/9/2011 2:14 PM, Fred wrote:
>
>
> So you are saying that the statement
> printf( "Hello, World!\n" );
> provokes undefined behavior, since I am calling it
> as if it were a function returning void rather than
> int n;
> n = printf( "Hello, World!\n" );
> where I am calling it as a function returning an int?

Please don't presume to tell others what they are saying. Your
assertion beginning with "So you are saying" is simply false. It is not
true that Keith was saying what follows, and for a simple reason: what
follows is completely false. You are _not_ calling it as a function
returning void; you are simply discarding the return value.
So, in addition to making false claims about what Keith wrote, you are
showing a lack of familiarity with elementary aspects of the C language.

Shao Miller

5/9/2011 7:15:00 PM

0

On 5/9/2011 1:51 PM, Keith Thompson wrote:
....C99 6.8.3 describes statement expressions (an
> expression with a semicolon added to the end of it can be used as a
> statement). The semantics are:
>
> The expression in an expression statement is evaluated as a void
> expression for its side effects.
>
> ...
>
> Given the current wording, I suppose one could argue that evaluating a
> printf call "as a void expression" means calling printf *as if* it
> returned void, and therefore the behavior is undefined. But I'm certain
> that that's not the intent, since it would break most C programs.
>
> Looks like another question for comp.std.c.
>

I'm certain of the same, but not so certain one could argue that
argument. Since the outermost expression is a function call, and that
expression has a result type, then I think 6.3.2.2p1 would allow for the
value to be discarded just as you suggest it ought.

Keith Thompson

5/9/2011 7:49:00 PM

0

Martin Ambuhl <mambuhl@earthlink.net> writes:
> On 5/9/2011 2:14 PM, Fred wrote:
>> So you are saying that the statement
>> printf( "Hello, World!\n" );
>> provokes undefined behavior, since I am calling it
>> as if it were a function returning void rather than
>> int n;
>> n = printf( "Hello, World!\n" );
>> where I am calling it as a function returning an int?
>
> Please don't presume to tell others what they are saying. Your
> assertion beginning with "So you are saying" is simply false. It is not
> true that Keith was saying what follows, and for a simple reason: what
> follows is completely false. You are _not_ calling it as a function
> returning void; you are simply discarding the return value.
> So, in addition to making false claims about what Keith wrote, you are
> showing a lack of familiarity with elementary aspects of the C language.

Given the wording of C99 6.8.3p2, which says that the call "is
evaluated as a void expression", it's not an unreasonable question.
(And yes, it was a question, not an assertion; note the question
mark at the end. "are you" might have been better than "you are",
but I'm not going to worry about it.)

Fred, was your question based on a (mis)reading of C99 6.8.3p2?
I'm arguing in comp.std.c that it should be re-worded; showing that
someone was actually led astray by the current wording would help
my argument.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"