473,553 Members | 3,116 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Arithmetic on function address

Given this code:
void f(void){}
int main(void){retu rn (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?
Nov 14 '05 #1
21 1756
Stephen Biggs wrote:

Given this code:
void f(void){}
int main(void){retu rn (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?

--
Er*********@sun .com
Nov 14 '05 #2
Eric Sosman <Er*********@su n.com> wrote in
news:40******** *******@sun.com :
Stephen Biggs wrote:

Given this code:
void f(void){}
int main(void){retu rn (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.
Nov 14 '05 #3
Stephen Biggs wrote:

Eric Sosman <Er*********@su n.com> wrote in
news:40******** *******@sun.com :
Stephen Biggs wrote:

Given this code:
void f(void){}
int main(void){retu rn (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.

--
Er*********@sun .com
Nov 14 '05 #4
"Stephen Biggs" <Sp******@AreLo wLifes.com-INVALID-MUNGED> wrote in message
news:c6******** **@news2.netvis ion.net.il...
Given this code:
void f(void){}
int main(void){retu rn (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() ;).
Nov 14 '05 #5

On Fri, 23 Apr 2004, Stephen Biggs wrote:

Eric Sosman <Er*********@su n.com> wrote...
Stephen Biggs wrote:

Given this code:
void f(void){}
int main(void){retu rn (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

Nov 14 '05 #6

"Stephen Biggs"
Given this code:
void f(void){}
int main(void){retu rn (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?
Nov 14 '05 #7
Eric Sosman <Er*********@su n.com> wrote in
news:40******** *******@sun.com :
Stephen Biggs wrote:

Eric Sosman <Er*********@su n.com> wrote in
news:40******** *******@sun.com :
> Stephen Biggs wrote:
>>
>> Given this code:
>> void f(void){}
>> int main(void){retu rn (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.
Nov 14 '05 #8
Stephen Biggs <Sp******@AreLo wLifes.com-INVALID-MUNGED> writes:
Given this code:
void f(void){}
int main(void){retu rn (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){prin tf("(int)f+5 = %d\n", (int)f+5);retur n 0;}

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

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #9
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 (cb********@yah oo.com) (cb********@wor ldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net> USE worldnet address!

Nov 14 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
1445
by: dan | last post by:
Hello, An Iterator class declares a data member that points to the current index of an array within a container class. It also implements a member function that determines whether or not the data member is pointing to the last index in the array using pointer arithmetic. class CIterator { public: CIterator(CContainer& c) : myContainer,
21
2055
by: MOvetsky | last post by:
Is the following code ISO C++ standard compliant? If yes, is it guaranteed that it will not crash on compliant platforms? If yes, will it print "Pointers are equal" on any compliant platform? Will answers be the same if p points to local memory or string literal? char *p = new char; char *p1 = p-1; p1 = p1 + 1;
22
4785
by: Christopher Benson-Manica | last post by:
Is adding 0 to a pointer to non-void that is equal to NULL legal? int *p=NULL; p+=0; -- Christopher Benson-Manica | I *should* know what I'm talking about - if I ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
3
2189
by: randomtalk | last post by:
hello everyone! Well, recently i've been trying to pick up c and see what is pointer all about (been programming in lisp/python for the better part of my last two years).. mmm.. I'm currently reading The C Programming Language Second Edition.. When i hit on pointer arithmetic example, i have no idea what's happening, hopefully some of...
1
2393
by: Satpreet | last post by:
I'm looking to simulate the behavior of a digital hardware arithmetic block in a C/C++ program. I was just wondering if there are any libraries (with datatypes and overloaded operators etc.) available for arithmetic operations on Fixed/Block-Floating Point variables ?? Alternatively could anyone throw me a pointer to sample code if...
7
528
by: barikat | last post by:
int a; int *Ptr1, *Ptr2; Ptr1 = a; Ptr1++; Ptr2 = a; printf("Ptr1 : %p\n", Ptr1); printf("Ptr2 : %p\n\n", Ptr2);
4
4689
by: Thomas Kreuzer | last post by:
Hello everyone, I have a question regarding how to interpret a string. Basically I want to write a little calculator, I will type something like "12+69*12-44/2" and then want my program to compute it into the result :) I experimented a bit with strtok and the like, but I think I am not sure how I should approach this problem. The...
26
3029
by: Bill Reid | last post by:
Bear with me, as I am not a "professional" programmer, but I was working on part of program that reads parts of four text files into a buffer which I re-allocate the size as I read each file. I read some of the items from the bottom up of the buffer, and some from the top down, moving the bottom items back to the new re-allocated bottom on...
8
1895
by: subramanian100in | last post by:
Supoose we have, int x; int *p = &x; int *q; q = p + 1;
0
7772
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8007
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7526
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7852
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6109
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5133
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3525
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1990
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1106
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.