Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Arithmetic on function address

Reply
Thread Tools

Arithmetic on function address

 
 
Stephen Biggs
Guest
Posts: n/a
 
      04-23-2004
Given this code:
void f(void){}
int main(void){return (int)f+5;}

Is there anything wrong with this in terms of the standards? Is this legal
C code? One compiler I'm working with compiles this quietly, even with the
most stringent and pedantic ANSI and warning levels, but generates code
that only loads the address of "f" and fails to make the addition before
returning a value from "main".

GCC "does the right thing".

Is there something I'm missing?
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      04-23-2004
Stephen Biggs wrote:
>
> Given this code:
> void f(void){}
> int main(void){return (int)f+5;}
>
> Is there anything wrong with this in terms of the standards?


Yes and no. The Standard permits you to cast a pointer
value (even a function pointer value) to an integer, but it
does not guarantee that the result is useful or even usable.

> Is this legal C code?


Legal but useless.

> One compiler I'm working with compiles this quietly, even with the
> most stringent and pedantic ANSI and warning levels, but generates code
> that only loads the address of "f" and fails to make the addition before
> returning a value from "main".
>
> GCC "does the right thing".
>
> Is there something I'm missing?


Your marbles, perhaps. What are you trying to
accomplish with this ill-defined operation?

--

 
Reply With Quote
 
 
 
 
Stephen Biggs
Guest
Posts: n/a
 
      04-23-2004
Eric Sosman <> wrote in
news::

> Stephen Biggs wrote:
>>
>> Given this code:
>> void f(void){}
>> int main(void){return (int)f+5;}
>>
>> Is there anything wrong with this in terms of the standards?

>
> Yes and no. The Standard permits you to cast a pointer
> value (even a function pointer value) to an integer, but it
> does not guarantee that the result is useful or even usable.



But, it then should allow you to add a value to that integer, as the
code says, no? Is this what you mean by no guarantees of it being
usable?

>
>> Is this legal C code?

>
> Legal but useless.



Ok, fine... I agree completely that it is useless, but shouldn't correct
code be generated for it?

>
>> One compiler I'm working with compiles this quietly, even with the
>> most stringent and pedantic ANSI and warning levels, but generates
>> code that only loads the address of "f" and fails to make the
>> addition before returning a value from "main".
>>
>> GCC "does the right thing".
>>
>> Is there something I'm missing?

>
> Your marbles, perhaps. What are you trying to
> accomplish with this ill-defined operation?
>


Thank you for that ... I am not trying to accomplish anything besides
running the GCC testsuite on some other compiler that I am trying to
analyze. This is part of the testsuite and passes with GCC, no
problem... I was just wondering if this is a bug in the compiler that I
am trying to run on this code? I want to be sure that this should
generate code correctly before I cry "bug". That is, that it should
generate code to add the constant after the pointer is converted to an
integer.

Thanks for any help.
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      04-23-2004
Stephen Biggs wrote:
>
> Eric Sosman <> wrote in
> news::
>
> > Stephen Biggs wrote:
> >>
> >> Given this code:
> >> void f(void){}
> >> int main(void){return (int)f+5;}
> >>
> >> Is there anything wrong with this in terms of the standards?

> >
> > Yes and no. The Standard permits you to cast a pointer
> > value (even a function pointer value) to an integer, but it
> > does not guarantee that the result is useful or even usable.

>
> But, it then should allow you to add a value to that integer, as the
> code says, no? Is this what you mean by no guarantees of it being
> usable?


If you're testing compilers (as you say later on), you really
ought to get yourself a copy of the Standard -- which says (in
section 6.2.3, paragraph 6):

Any pointer type may be converted to an integer type.
Except as previously specified [not relevant here],
the result is implementation-defined. If the result
cannot be represented in the integer type, the behavior
is undefined. The result need not be in the range of
values of any integer type.

So: The result of the conversion is implementation-defined, and
need not be a valid value for an `int', and any attempt to create
an invalid value causes undefined behavior. That's "unusable" in
my book. (Gurus: Contrast this paragraph with the apparently
stronger conditions of 6.3.1.3/3: pointer-to-int can generate
U.B. instead of raising an implementation-defined signal.)

> >> Is this legal C code?

> >
> > Legal but useless.

>
> Ok, fine... I agree completely that it is useless, but shouldn't correct
> code be generated for it?


It's hard to understand what "correct" means when describing
what might be undefined behavior. I think you need to do two
things before concluding that the generated code is "incorrect:"
You need to consult the compiler's own documentation to find how
it defines the conversion result, and you then need to determine
whether the result is in range for an `int'. Then:

- If the conversion result is defined but out of range,
you have no grounds for complaint. Any and all behaviors
(hence any and all generated code) are "correct."

- If the conversion result is defined and in range, you
may have reason to complain.

- If the conversion result is not defined, you have reason
to complain about the documentation, but not (yet) about
the code generation.

One observation about testing compilers: They usually must
obey several standards, not just one, and some of these may be
just "usual practice" rather than formal standards. That is,
the C Standard represents a sort of "non-negotiable minimum"
for a C implementation, but a C implementation that did *only*
what the Standard required would not enjoy much success. The
prospective users will also want POSIX support and/or Windows
support, they'll want "friendly" behavior when they do things
like clear a pointer to all-bits-zero, they'll want CHAR_BIT
to equal (not exceed) 8, they'll want various guarantees about
signal() behavior, and so on. They will *not* want the strictly-
conforming but user-hostile C compiler of the DeathStation 9000!

Next time you climb into your car, pause and take a look
around. How many of the things you see could be removed without
actually removing the car's ability to get you from Here to
There? Rip out the radio, the air conditioner, the leather
seats, the back seat, the side and rear windows, the power
steering -- you'll still have a strictly-conforming car, but
you might not want to drive it much.

--

 
Reply With Quote
 
Alex Fraser
Guest
Posts: n/a
 
      04-23-2004
"Stephen Biggs" <-INVALID-MUNGED> wrote in message
news:c6bjka$sct$...
> Given this code:
> void f(void){}
> int main(void){return (int)f+5;}
>
> Is there anything wrong with this in terms of the standards? Is this
> legal C code? One compiler I'm working with compiles this quietly, even
> with the most stringent and pedantic ANSI and warning levels, but
> generates code that only loads the address of "f" and fails to make the
> addition before returning a value from "main".


Perhaps it optimised the addition away by moving f() .


 
Reply With Quote
 
Arthur J. O'Dwyer
Guest
Posts: n/a
 
      04-23-2004

On Fri, 23 Apr 2004, Stephen Biggs wrote:
>
> Eric Sosman <> wrote...
> > Stephen Biggs wrote:
> >>
> >> Given this code:
> >> void f(void){}
> >> int main(void){return (int)f+5;}
> >>
> >> Is there anything wrong with this in terms of the standards?

> >
> > Yes and no. The Standard permits you to cast a pointer
> > value (even a function pointer value) to an integer, but it
> > does not guarantee that the result is useful or even usable.

>
> But, it then should allow you to add a value to that integer, as the
> code says, no? Is this what you mean by no guarantees of it being
> usable?


[This explanation based on N869 6.3.2.3#6.]

Not necessarily. The implementation might for instance map the
address of 'f' onto 'INT_MAX', thus producing signed-int overflow
when you try to add 5 to it. *Then*, and only then, is your program
allowed to defrost your refrigerator.
Alternatively, the implementation could map 'f' directly onto a
trap representation in 'int'; then, *any* attempt to use the value
of '(int)f' at all would trigger undefined behavior. (Note that
'(int)f' itself is still a valid construct on such systems; you
can take the 'sizeof ((int)f)' with impunity, but that's all you can
do.)
Finally, according to the word of the C99 draft standard, the
implementation is allowed to map the address of 'f' directly onto
a number so large that 'int' can't hold it. Instant undefined
behavior! (Except IMO in the case of 'sizeof', as above.)


> >> Is this legal C code?

> >
> > Legal but useless.

>
>
> Ok, fine... I agree completely that it is useless, but shouldn't correct
> code be generated for it?


If it's completely useless --- and in fact could legitimately do
*anything at all* to your machine --- then what, pray tell, would be
the "correct code" you'd expect to see generated? "Garbage in,
garbage out" is the rule that applies here. Well, more precisely,
"Something that might or might not produce garbage in, something that
might or might not be garbage out."

> >> One compiler I'm working with compiles this quietly, even with the
> >> most stringent and pedantic ANSI and warning levels, but generates
> >> code that only loads the address of "f" and fails to make the
> >> addition before returning a value from "main".


You mean that on this compiler, the expressions

(int)f AND (int)f+5

compile to the same machine code? This is odd, but perfectly legitimate,
behavior for a conforming optimizing C compiler as long as it documents
its behavior in a conforming fashion. There's nothing wrong with your
compiler (although I would say it's a weird one); there is something
wrong with your test suite.

[BTW, if any experts could explain what 6.3.2.3 #6 means by
"except as previously specified," I'd love to hear it. I don't
recall any "previously specified" cases of the pointer-to-integer
cast's being defined.]

-Arthur

 
Reply With Quote
 
Malcolm
Guest
Posts: n/a
 
      04-23-2004

"Stephen Biggs"
> Given this code:
> void f(void){}
> int main(void){return (int)f+5;}
>
> One compiler ... generates code that only loads the address of "f"
> and fails to make the addition before returning a value from "main".
>

Something funny is going on. As others have pointed out legally the compiler
can do anything with such a construct, but if it allows a cast from main to
f then it should put the address of main() in the integer register and then
add five to it. However how are you checking this? Is it by writing a second
program in which main() is possibly in a different position?
Why not see if you can get an assembly lisiting of the program to see what
code is being compiled?


 
Reply With Quote
 
Stephen Biggs
Guest
Posts: n/a
 
      04-23-2004
Eric Sosman <> wrote in
news::

> Stephen Biggs wrote:
>>
>> Eric Sosman <> wrote in
>> news::
>>
>> > Stephen Biggs wrote:
>> >>
>> >> Given this code:
>> >> void f(void){}
>> >> int main(void){return (int)f+5;}
>> >>
>> >> Is there anything wrong with this in terms of the standards?
>> >
>> > Yes and no. The Standard permits you to cast a pointer
>> > value (even a function pointer value) to an integer, but it
>> > does not guarantee that the result is useful or even usable.

>>
>> But, it then should allow you to add a value to that integer, as the
>> code says, no? Is this what you mean by no guarantees of it being
>> usable?

>
> If you're testing compilers (as you say later on), you really
> ought to get yourself a copy of the Standard



Yes... I should, but I am doing this as an employee of a company and
they are too cheap to buy it...


> -- which says (in
> section 6.2.3, paragraph 6):
>
> Any pointer type may be converted to an integer type.
> Except as previously specified [not relevant here],
> the result is implementation-defined. If the result
> cannot be represented in the integer type, the behavior
> is undefined. The result need not be in the range of
> values of any integer type.
>
> So: The result of the conversion is implementation-defined, and
> need not be a valid value for an `int', and any attempt to create
> an invalid value causes undefined behavior. That's "unusable" in
> my book. (Gurus: Contrast this paragraph with the apparently
> stronger conditions of 6.3.1.3/3: pointer-to-int can generate
> U.B. instead of raising an implementation-defined signal.)



Ok... I understand this... that's just it... the code that this compiler
generates does the conversion and actually returns the address of the
function as an integer. It just silently discards the addition. If
this is implementation behavior, shouldn't it (as you say below about
compilers needing to give more than just what the standard says) either
complain about an invalid value or do the addition also, since it
accepts the conversion in the first place? The function address is
converted to an integer since this is what is returned, so the integer
value should be available for more computation if needed.

Any other behavior, such as what is happening here, is a bug in the
compiler IMHO.

>
>> >> Is this legal C code?
>> >
>> > Legal but useless.

>>
>> Ok, fine... I agree completely that it is useless, but shouldn't
>> correct code be generated for it?

>
> It's hard to understand what "correct" means when describing
> what might be undefined behavior.



According to the definition above about "undefined behavior", as I read
it, since function addresses as well as all other pointers in this
compiler are the same size as an int (32 bits), then doing this
conversion is definitely defined. Thus, dropping the addition after
making the conversion is a bug.

> I think you need to do two
> things before concluding that the generated code is "incorrect:"
> You need to consult the compiler's own documentation to find how
> it defines the conversion result, and you then need to determine
> whether the result is in range for an `int'. Then:
>
> - If the conversion result is defined but out of range,
> you have no grounds for complaint. Any and all behaviors
> (hence any and all generated code) are "correct."
>
> - If the conversion result is defined and in range, you
> may have reason to complain.



That is exactly what is happening here... a function pointer or any
other pointer is the same size as an unsigned int (32 bits). Smaller
actually, here, so it fits in a signed int.

>
> - If the conversion result is not defined, you have reason
> to complain about the documentation, but not (yet) about
> the code generation.



See above. If I am reading right what you quoted from the standard, then
the behavior is defined. If the conversion result was not defined, then
shouldn't, at least, a warning (or even a pedantic remark) be generated?
This compiler is extremely anal about other aspects of ANSI/ISO C.

>
> One observation about testing compilers: They usually must
> obey several standards, not just one, and some of these may be
> just "usual practice" rather than formal standards. That is,
> the C Standard represents a sort of "non-negotiable minimum"
> for a C implementation, but a C implementation that did *only*
> what the Standard required would not enjoy much success. The
> prospective users will also want POSIX support and/or Windows
> support, they'll want "friendly" behavior when they do things
> like clear a pointer to all-bits-zero, they'll want CHAR_BIT
> to equal (not exceed) 8, they'll want various guarantees about
> signal() behavior, and so on. They will *not* want the strictly-
> conforming but user-hostile C compiler of the DeathStation 9000!
>
> Next time you climb into your car, pause and take a look
> around. How many of the things you see could be removed without
> actually removing the car's ability to get you from Here to
> There? Rip out the radio, the air conditioner, the leather
> seats, the back seat, the side and rear windows, the power
> steering -- you'll still have a strictly-conforming car, but
> you might not want to drive it much.



Yes... but what "standard" is this car "conforming" to?

>

Thanks for the help, Eric.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      04-24-2004
Stephen Biggs <-INVALID-MUNGED> writes:
> Given this code:
> void f(void){}
> int main(void){return (int)f+5;}
>
> Is there anything wrong with this in terms of the standards? Is this legal
> C code? One compiler I'm working with compiles this quietly, even with the
> most stringent and pedantic ANSI and warning levels, but generates code
> that only loads the address of "f" and fails to make the addition before
> returning a value from "main".
>
> GCC "does the right thing".
>
> Is there something I'm missing?


That's a very odd way to examine the value of an integer expression.
On many systems, the value returned from main doesn't directly map to
the status returned by the program (returning just the low-order 8
bits is common).

You shouldn't expect the result of casting a function address to int
to be at all meaningful, but it does seem odd that you're not seeing
the addition of 5 in the generated code. Is it possible that the
addition is being done during compilation or linking?

Try something like this:

#include <stdio.h>
void f(void){}
int main(void){printf("(int)f+5 = %d\n", (int)f+5);return 0;}

with and without the "+5" (but be aware that adding code to main()
could change the address of f()).

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      04-24-2004
Eric Sosman wrote:
>

.... snip ...
>
> Next time you climb into your car, pause and take a look
> around. How many of the things you see could be removed without
> actually removing the car's ability to get you from Here to
> There? Rip out the radio, the air conditioner, the leather
> seats, the back seat, the side and rear windows, the power
> steering -- you'll still have a strictly-conforming car, but
> you might not want to drive it much.


Apart from the leather seats, that sounds like a 1954 MG TD. I
would be happy to drive one.

--
Chuck F () ()
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

 
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
Arithmetic on function address pete b C Programming 20 06-01-2010 05:58 PM
Address Arithmetic aistone@gmail.com C++ 14 07-10-2006 12:03 AM
Address of array behavior in pointer arithmetic joshc C Programming 16 06-15-2006 10:14 PM
A kind of arithmetic for subnetting and ip address management lily Cisco 0 05-08-2006 09:32 AM
Usual Arithmetic Conversions-arithmetic expressions joshc C Programming 5 03-31-2005 02:23 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57