By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,199 Members | 1,742 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,199 IT Pros & Developers. It's quick & easy.

get the address of a function??

P: n/a
Is the following program print the address of the function?

void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}

please advice. thanks....

Nov 1 '06 #1
Share this Question
Share on Google+
54 Replies


P: n/a
John said:
Is the following program print the address of the function?

void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}
The behaviour of the program is undefined in at least three ways. So - maybe
it will do what you want, and maybe it won't. Maybe it will do what you
want /and/ something else that it doesn't tell you about. No way to tell.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Nov 1 '06 #2

P: n/a
Richard Heathfield wrote:
John said:

>>Is the following program print the address of the function?

void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}


The behaviour of the program is undefined in at least three ways. So - maybe
it will do what you want, and maybe it won't. Maybe it will do what you
want /and/ something else that it doesn't tell you about. No way to tell.
Is there a prize for spotting the three ways?

--
Ian Collins.
Nov 1 '06 #3

P: n/a
In article <4q************@individual.net>,
Ian Collins <ia******@hotmail.comwrote:
>>>void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}
>The behaviour of the program is undefined in at least three ways. So - maybe
Is there a prize for spotting the three ways?
No <stdio.h>, two errors in the declaration of main(), passing a
pointer to printf() with a %d format. And despite all that, it will
probably work.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 1 '06 #4

P: n/a
"John" <ja*****@gmail.comwrites:
Is the following program print the address of the function?

void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}
No.

"void hello()" is acceptable, but "void hello(void)" is better.

Calling printf with no visible prototype invokes undefined behavior.
The "#include <stdio.h>" is mandatory (even if your compiler doesn't
complain that it's missing).

main returns int, not void. If you learned "void main()" from a
textbook, stop using it and find a better one. The comp.lang.c FAQ is
at <http://www.c-faq.com/>; question 18.10 recommends some good books.
Make it "int main(void)".

printf's "%d" option requires an argument of type int. You're giving
it a function pointer. This invokes undefined behavior.

Since main returns int, you should return an int. Add "return 0;"
after your printf call. This isn't necessarily mandatory, but there's
no reason not to do it.

The printf format for a pointer value is "%p" -- but it can be used
*only* for object pointers, not for function pointers. Actually, "%p"
expects an argument of type void*, and since printf is a variadic
function, an ordinary pointer will not be implicitly converted to
void*; you have to do it yourself.

So the following will work to print the value of an object pointer:

int x;
int *ptr = &x;
printf("ptr = %p\n", (void*)ptr);

*But* there's no defined conversion from a function pointer to void*
(though some compilers may support it as an extension), so this won't
necessarily work for printing the address of your function.

(You can interpret a function pointer value as a sequence of bytes
(unsigned chars) and print their values, but I suspect that's more
than you want to deal with right now.)

Why do you want to do this? If you were to print the address of your
function, what would you do with the information?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 1 '06 #5

P: n/a
In article <ei**********@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <ri*****@cogsci.ed.ac.ukwrote:
>In article <4q************@individual.net>,
Ian Collins <ia******@hotmail.comwrote:
>>>>void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}
>>The behaviour of the program is undefined in at least three ways. So - maybe
No <stdio.h>, two errors in the declaration of main(), passing a
pointer to printf() with a %d format. And despite all that, it will
probably work.
And a pointer might be the wrong size to use with %d, so possibly
only some of the bytes of the pointer will be converted for output.
--
I was very young in those days, but I was also rather dim.
-- Christopher Priest
Nov 1 '06 #6

P: n/a
John:
Is the following program print the address of the function?

void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}

As far as I'm aware, the C Standard doesn't provide a "nice" way to print
function addresses. You could, however, print out the byte values which make
up the address... better than nothing.

void (*const pfunc)(void) = hello;

char unsigned const *p = (char unsigned const*)&pfunc;
char unsigned const *const pover = p + sizeof pfunc;

do printf("%u\n",(unsigned)*p++);
while (pover != p);

--

Frederick Gotham
Nov 1 '06 #7

P: n/a

John wrote:
Is the following program print the address of the function?

void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}

please advice. thanks....
Well, there are several problems. The %d conversion specifier is the
wrong one to use to print out a pointer value; you should use %p
instead, as it expects a pointer value of type void*. Unfortunately,
you wind up with a type mismatch anyway, as the type of "hello" in the
printf statement is implicitly converted to void (*)(), or a pointer to
a function returning void. Standard C does not allow for conversions
between object pointers (void *) and function pointers (void (*)()) and
vice-versa. Most implementations will do *something* that looks
reasonable, but it's technically not correct.

To top it off, main() returns int, not void. And you don't have a
prototype for printf() in scope (assuming this was the complete program
and not just a fragment).

Nov 1 '06 #8

P: n/a
ro******@ibd.nrc-cnrc.gc.ca (Walter Roberson) writes:
In article <ei**********@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <ri*****@cogsci.ed.ac.ukwrote:
[...]
>>No <stdio.h>, two errors in the declaration of main(), passing a
pointer to printf() with a %d format. And despite all that, it will
probably work.

And a pointer might be the wrong size to use with %d, so possibly
only some of the bytes of the pointer will be converted for output.
Size matters not.

Printing a pointer with a "%d" format invokes undefined behavior.
Printing only some of the bytes is merely one of the infinitely many
possible consequences. (Printing exactly what you expect is, of
course, another, but only if you're unlucky.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 1 '06 #9

P: n/a
Richard Tobin wrote:
In article <4q************@individual.net>,
Ian Collins <ia******@hotmail.comwrote:
The behaviour of the program is undefined in at least three ways.
So - maybe
Is there a prize for spotting the three ways?

No <stdio.h>, two errors in the declaration of main(), passing a
pointer to printf() with a %d format. And despite all that, it will
probably work.
What are the two errors in the declaration of main()?


Brian
Nov 2 '06 #10

P: n/a
On Wed, 2006-11-01 at 15:14 -0800, John wrote:
Is the following program print the address of the function?

void hello()
{ printf("hello\n");
}

void main()
{
printf("hello function=%d\n", hello);
}

please advice. thanks....
Well, it might. Or it might not. Or it might electrocute your dog. If
you don't have a dog, it may connect to a petstore site and get you one.
If you don't have an internet connection, it may fax an ISP and get you
one. If you don't have a fax modem, it might blow up your hard drive and
turn it into one.

In other words, you have undefined behaviour, and anything can happen.

The closest you can get to doing this correctly is:
1. Use "%p" instead of "%d" to print the value of a pointer.
2. Convert all pointers to void* when passing them to varadic functions
like printf(), scanf(), et al.
3. Realize that pointers-to-functions /cannot/ be converted to void*,
unlike pointers-to-objects. So, there's no way for you to do what you
want in standard C. Sorry.

--
Andrew Poelstra <http://www.wpsoftware.net>
For email, use 'apoelstra' at the above site.
"You're only smart on the outside." -anon.

Nov 2 '06 #11

P: n/a
2006-11-02 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
ro******@ibd.nrc-cnrc.gc.ca (Walter Roberson) writes:
>In article <ei**********@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <ri*****@cogsci.ed.ac.ukwrote:
[...]
>>>No <stdio.h>, two errors in the declaration of main(), passing a
pointer to printf() with a %d format. And despite all that, it will
probably work.

And a pointer might be the wrong size to use with %d, so possibly
only some of the bytes of the pointer will be converted for output.

Size matters not.

Printing a pointer with a "%d" format invokes undefined behavior.
Yeah, but we were talking about "probably will work" - the size/bytes
thing is one of the few aspects of it that has a reasonably large
probability of not working.
Printing only some of the bytes is merely one of the infinitely many
possible consequences. (Printing exactly what you expect is, of
course, another, but only if you're unlucky.)
Personally, I'd use %p with a void * cast - that's about as close to
portable as it gets (it might even be unspecified rather than undefined)
Nov 2 '06 #12

P: n/a
Jordan Abel <ra****@random.yi.orgwrites:
2006-11-02 <ln************@nuthaus.mib.org>,
Keith Thompson wrote:
>ro******@ibd.nrc-cnrc.gc.ca (Walter Roberson) writes:
>>In article <ei**********@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <ri*****@cogsci.ed.ac.ukwrote:
[...]
>>>>No <stdio.h>, two errors in the declaration of main(), passing a
pointer to printf() with a %d format. And despite all that, it will
probably work.

And a pointer might be the wrong size to use with %d, so possibly
only some of the bytes of the pointer will be converted for output.

Size matters not.

Printing a pointer with a "%d" format invokes undefined behavior.

Yeah, but we were talking about "probably will work" - the size/bytes
thing is one of the few aspects of it that has a reasonably large
probability of not working.
>Printing only some of the bytes is merely one of the infinitely many
possible consequences. (Printing exactly what you expect is, of
course, another, but only if you're unlucky.)

Personally, I'd use %p with a void * cast - that's about as close to
portable as it gets (it might even be unspecified rather than undefined)
I'm reasonably certain it's undefined behavior.

C99 6.3.2.3 defines the behavior of conversions involving pointers.
Since it says nothing about the behavior of a conversion from a
function pointer to void*, the behavior is undefined by omission.

But that raises an interesting point. Consider this:

#include <stdio.h>
int main(void)
{
void (*p)(void) = main;
void *foo = (void*)p;
printf("p = %p\n", p);
return 0;
}

The only relevant constraint on the cast operator (C99 6.5.4) is that
the type name and the operand both have to be scalar. So the cast
invokes undefined behavior, but it doesn't violate any constraint.

It seems a little odd, since it *could* have been treated like other
type mismatches. Attempting to add a function pointer and an integer,
or an object number and a double, is a constraint violation, but
attempting to convert a function pointer to void* isn't.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 2 '06 #13

P: n/a
Keith Thompson said:

<snip>
It seems a little odd, since it *could* have been treated like other
type mismatches. Attempting to add a function pointer and an integer,
or an object number and a double, is a constraint violation, but
attempting to convert a function pointer to void* isn't.
<shrugIt's a useful thing to be able to do, and I suspect that the
Committee would have liked to codify it, but felt unable so to do. They do
list it as a common extension, in one of the Appendicicices.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Nov 2 '06 #14

P: n/a
Andrew Poelstra wrote:
On Wed, 2006-11-01 at 15:14 -0800, John wrote:
>Is the following program print the address of the function?

The closest you can get to doing this correctly is:
1. Use "%p" instead of "%d" to print the value of a pointer.
2. Convert all pointers to void* when passing them to varadic functions
like printf(), scanf(), et al.
3. Realize that pointers-to-functions /cannot/ be converted to void*,
unlike pointers-to-objects. So, there's no way for you to do what you
want in standard C. Sorry.
When there's a will, there's a way. (Untested code follows)

void print_func(void (*p)())
{
unsigned char *a = (unsigned char *)&p;
size_t i, n = sizeof p;
for(i = 0; i < n; i++) printf("%02X", (unsigned int)a[i]);
}

If your bytes are greater than 8 bits, you can change the 02 to 04 or 08
in the printf string.

If function pointers are stored in LSB-first (little-endian) format then
the bytes will be the wrong way around.

--
Simon.
Nov 2 '06 #15

P: n/a
Simon Biber <ne**@ralmin.ccwrote:
Andrew Poelstra wrote:
On Wed, 2006-11-01 at 15:14 -0800, John wrote:
Is the following program print the address of the function?
The closest you can get to doing this correctly is:
1. Use "%p" instead of "%d" to print the value of a pointer.
2. Convert all pointers to void* when passing them to varadic functions
like printf(), scanf(), et al.
3. Realize that pointers-to-functions /cannot/ be converted to void*,
unlike pointers-to-objects. So, there's no way for you to do what you
want in standard C. Sorry.

When there's a will, there's a way. (Untested code follows)

void print_func(void (*p)())
{
unsigned char *a = (unsigned char *)&p;
size_t i, n = sizeof p;
for(i = 0; i < n; i++) printf("%02X", (unsigned int)a[i]);
}

If your bytes are greater than 8 bits, you can change the 02 to 04 or 08
in the printf string.
Or if you have C99, then you can cast to uint_least8_t, and use
PRIxLEAST8 from <inttypes.h>. BTW, I would use sizeof p directly, and
not bother with n. It's a compile-time constant, after all.

Richard
Nov 2 '06 #16

P: n/a
2006-11-02 <9s********************@bt.com>,
Richard Heathfield wrote:
Keith Thompson said:

<snip>
>It seems a little odd, since it *could* have been treated like other
type mismatches. Attempting to add a function pointer and an integer,
or an object number and a double, is a constraint violation, but
attempting to convert a function pointer to void* isn't.

<shrugIt's a useful thing to be able to do, and I suspect that the
Committee would have liked to codify it, but felt unable so to do. They do
list it as a common extension, in one of the Appendicicices.
Incidentally - is it legal to convert a function pointer to intptr_t,
when such a type is provided?
Nov 2 '06 #17

P: n/a
Jordan Abel <ra****@random.yi.orgwrote:
2006-11-02 <9s********************@bt.com>,
Richard Heathfield wrote:
Keith Thompson said:
It seems a little odd, since it *could* have been treated like other
type mismatches. Attempting to add a function pointer and an integer,
or an object number and a double, is a constraint violation, but
attempting to convert a function pointer to void* isn't.
<shrugIt's a useful thing to be able to do, and I suspect that the
Committee would have liked to codify it, but felt unable so to do. They do
list it as a common extension, in one of the Appendicicices.

Incidentally - is it legal to convert a function pointer to intptr_t,
when such a type is provided?
No. The definition of intptr_t speaks specifically of conversion to and
from void *, not any other type. Since any object pointer can also be
converted to and from void *, that also means that any object pointer
can be converted to a void *, to an intptr_t, back to a void *, and back
to the original type, and the result must compare equal to the original
pointer - but only object pointers.
Function pointers cannot portably be converted either to void *, to any
other object pointer type, or to intptr_t; not directly, and not
indirectly. They _can_ all be converted, losslessly, to one another, but
that isn't helpful if you want to print one.

Richard
Nov 2 '06 #18

P: n/a
>Jordan Abel <ra****@random.yi.orgwrote:
>Incidentally - is it legal to convert a function pointer to intptr_t,
when such a type is provided?
In article <45***************@news.xs4all.nl>,
Richard Bos <rl*@hoekstra-uitgeverij.nlwrote:
>No. ...
Function pointers cannot portably be converted either to void *, to any
other object pointer type, or to intptr_t; not directly, and not
indirectly. They _can_ all be converted, losslessly, to one another, but
that isn't helpful if you want to print one.
Right.

Fundamentally, this allows implementations to use "fatter" pointers
for "pointer to <function ...>" types than for "pointer to <data
type>" types. The IBM AS/400, at least, makes use of this property.
(Intel x86 compilers used to use it too, back in the days of "near"
and "far" pointers, in various models.)

Note that one can always store the function pointers in data objects
of type "pointer to <function ...>". That is, given some function
T F(arglist), we just declare an actual object:

T (*fp)(arglist); /* e.g., int (*fp)(int, char **) */

and store the pointer to that function in that data object. Now we
take the data object's address:

T (**pfp)(arglist) = &fp;

and we have successfully "smuggled" the function-pointer value inside
a data object, whose address we can print. (Of course, it may be the
*contents* of that address that are in some manner "interesting", but
the address is printable, and is specific to "pfp".)

Now suppose that, for every function F that exists in some given
C program P, we were able to -- in some mechanical manner -- invent
a static-storage-duration pointer of the appropriate type, and set
it to point to F. For instance, if program P contains, among other
things:

int foo(int, char **);
void bar(double);

we would have to create pointers p_foo and p_bar:

int (*p_foo)(int, char **) = foo;
void (*p_bar)(double) = bar;

If we could do this, we would have a data pointer corresponding to
each function pointer, and could substitute the data-pointer values
for every instance of the function pointer value, at the cost of
having to indirect through that data pointer to find the function.
That is, we could rewrite the call:

result = foo(3, &x);

as:

result = (*p_foo)(3, &x);

The question is, can a C compiler do this "mechanically"? The
answer is obviously "yes": every time it encounters an actual
function definition, it emits a definition of the corresponding
pointer -- using the implementation's name space, so something like
__func_foo instead of p_foo -- initialized to point to that function.
Every time it encounters a declaration of a function, it emits a
corresponding declaration (with "extern") for that same pointer.
Every time it encounters a call to a function F, it loads the
pointer from __func_F.

Having done this, the compiler has, in effect, converted all
functions to data objects, which are (in this case) all named
__func_<whateverinstead of just <whatever>. If we were to collect
up all these objects in some manner (say, at link time), and label
them "function descriptors", we could put them in a "function
descriptor table".

Using this technique, a C compiler that was *not* allowed to use
"fat" pointers to point to functions could put the "real" function
pointers -- which could in fact be enormously fat -- into a function
descriptor table, and make the "function pointer" that the programmer
sees be an ordinary data pointer, pointing into the descriptor
table. This is, in fact, exactly what some (but not all) C compilers
do, for architectures on which the underlying machine-code level
function pointers are "fatter" than ordinary data pointers. A C
standard that *required* this would be no more restrictive, in
terms of computing power at least, than the current C standards.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 2 '06 #19

P: n/a
On Thu, 2 Nov 2006 12:30:24 UTC, Jordan Abel <ra****@random.yi.org>
wrote:
2006-11-02 <9s********************@bt.com>,
Richard Heathfield wrote:
Keith Thompson said:

<snip>
It seems a little odd, since it *could* have been treated like other
type mismatches. Attempting to add a function pointer and an integer,
or an object number and a double, is a constraint violation, but
attempting to convert a function pointer to void* isn't.
<shrugIt's a useful thing to be able to do, and I suspect that the
Committee would have liked to codify it, but felt unable so to do. They do
list it as a common extension, in one of the Appendicicices.

Incidentally - is it legal to convert a function pointer to intptr_t,
when such a type is provided?
No, a function pointer can't converted to a data pointer and back.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
Nov 2 '06 #20

P: n/a
Default User wrote:
Richard Tobin wrote:
>In article <4q************@individual.net>,
Ian Collins <ia******@hotmail.comwrote:
>>>The behaviour of the program is undefined in at least three ways.
So - maybe
>>Is there a prize for spotting the three ways?
No <stdio.h>, two errors in the declaration of main(), passing a
pointer to printf() with a %d format. And despite all that, it will
probably work.

What are the two errors in the declaration of main()?
main() can be one of:

int main(void) { /* ... */ }

or

int main(int, char**) { /* ... */ }

I think this is documented in the section dealing with program startup.
Nov 2 '06 #21

P: n/a
2006-11-02 <Si*****************@nnrp.ca.mci.com!nnrp1.uunet.c a>,
Clever Monkey wrote:
Default User wrote:
>Richard Tobin wrote:

What are the two errors in the declaration of main()?
main() can be one of:

int main(void) { /* ... */ }

or

int main(int, char**) { /* ... */ }

I think this is documented in the section dealing with program startup.
Yeah, but I count one error, not two.

Unless you're saying all of the following are therefore invalid
int main() { }
int main(c,v) char **v; { }
main() { }
main(c,v) char **v; { }
main(void) { }
[and other combinations]
Nov 2 '06 #22

P: n/a
In article <Si*****************@nnrp.ca.mci.com!nnrp1.uunet.c a>,
Clever Monkey <cl**************@hotmail.com.invalidwrote:
>main() can be one of:
>int main(void) { /* ... */ }
>or
>int main(int, char**) { /* ... */ }
>I think this is documented in the section dealing with program startup.
The second of those is a prototype followed (in violation of
syntax) by a block. C89 2.1.2.2.1 Program Startup says specifically that
"The implementation declares no prototype for this function."

The declarations that are shown in C89 do not use char** argv
but instead use char *argv[]

And that section only applies to hosted environments; in freestanding
environments, "the name and type of the function called at program
startup are implementation-defined". So unless you impose the
restriction of hosted environment, main might have weird and wonderful
arguements, and might not even be called main().

--
There are some ideas so wrong that only a very intelligent person
could believe in them. -- George Orwell
Nov 2 '06 #23

P: n/a
Walter Roberson wrote:
In article <Si*****************@nnrp.ca.mci.com!nnrp1.uunet.c a>,
Clever Monkey <cl**************@hotmail.com.invalidwrote:
>main() can be one of:
>int main(void) { /* ... */ }
>or
>int main(int, char**) { /* ... */ }
>I think this is documented in the section dealing with program startup.

The second of those is a prototype followed (in violation of
syntax) by a block. C89 2.1.2.2.1 Program Startup says specifically that
"The implementation declares no prototype for this function."

The declarations that are shown in C89 do not use char** argv
but instead use char *argv[]
My recollection is that it says something like "or equivalent", but my
memory might be wrong.
And that section only applies to hosted environments; in freestanding
environments, "the name and type of the function called at program
startup are implementation-defined". So unless you impose the
restriction of hosted environment, main might have weird and wonderful
arguements, and might not even be called main().
Again, I think this is covered by some verbiage like "in some other
implementation-defined manner".
Nov 2 '06 #24

P: n/a
2006-11-02 <ei**********@canopus.cc.umanitoba.ca>,
Walter Roberson wrote:
In article <Si*****************@nnrp.ca.mci.com!nnrp1.uunet.c a>,
Clever Monkey <cl**************@hotmail.com.invalidwrote:
>>main() can be one of:
>>int main(void) { /* ... */ }
>>or
>>int main(int, char**) { /* ... */ }
>>I think this is documented in the section dealing with program startup.

The second of those is a prototype followed (in violation of
syntax) by a block.
It's in violation of something, but it ain't syntax, and it's nothing to
do with the fact that it's a prototype.
C89 2.1.2.2.1 Program Startup says specifically that
"The implementation declares no prototype for this function."
The implementation doesn't. That doesn't mean the program can't.
The declarations that are shown in C89 do not use char** argv
but instead use char *argv[]
Same thing.
Nov 2 '06 #25

P: n/a
Jordan Abel <ra****@random.yi.orgwrites:
[...]
Incidentally - is it legal to convert a function pointer to intptr_t,
when such a type is provided?
It's "legal" in the sense that it's not a constraint violation, but it
invokes undefined behavior.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 2 '06 #26

P: n/a
Simon Biber wrote:
void print_func(void (*p)())
{
unsigned char *a = (unsigned char *)&p;
That's undefined.
The standard doesn't describe what happens
when a function pointer is converted to an object pointer.
6.3.2.3 Pointers

7 A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type.

8 A pointer to a function of one type may be converted to a
pointer to a function of another type and back again;
the result shall compare equal to the original pointer.

--
pete
Nov 2 '06 #27

P: n/a
Frederick Gotham wrote:
As far as I'm aware,
the C Standard doesn't provide a "nice" way to print
function addresses.
void (*const pfunc)(void) = hello;

char unsigned const *p = (char unsigned const*)&pfunc;
The standard doesn't provide a way to convert a function pointer
to an object pointer either.

--
pete
Nov 2 '06 #28

P: n/a
pete <pf*****@mindspring.comwrites:
Simon Biber wrote:
>void print_func(void (*p)())
{
unsigned char *a = (unsigned char *)&p;

That's undefined.
The standard doesn't describe what happens
when a function pointer is converted to an object pointer.
That's not what the code is trying to do. p is a function pointer,
but &p is an object pointer (it points to the function pointer). The
code, if I recall correctly, decomposes the representation of the
function pointer to a sequence of bytes to be printed. The results
are implementation-defined, but it's legal, and it's the only portable
way to print (a representation of) the value of a function pointer.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 2 '06 #29

P: n/a
pete wrote:
>
Frederick Gotham wrote:
As far as I'm aware,
the C Standard doesn't provide a "nice" way to print
function addresses.
void (*const pfunc)(void) = hello;

char unsigned const *p = (char unsigned const*)&pfunc;

The standard doesn't provide a way to convert a function pointer
to an object pointer either.
But now that I've read Keith Thompson's correction
to something similar that I wrote elsethread,
I think that my remark is irrelevant to your code.

--
pete
Nov 3 '06 #30

P: n/a
Keith Thompson wrote:
>
pete <pf*****@mindspring.comwrites:
Simon Biber wrote:
void print_func(void (*p)())
{
unsigned char *a = (unsigned char *)&p;
That's undefined.
The standard doesn't describe what happens
when a function pointer is converted to an object pointer.

That's not what the code is trying to do. p is a function pointer,
but &p is an object pointer (it points to the function pointer). The
code, if I recall correctly, decomposes the representation of the
function pointer to a sequence of bytes to be printed. The results
are implementation-defined, but it's legal, and it's the only portable
way to print (a representation of) the value of a function pointer.
Thanks.

--
pete
Nov 3 '06 #31

P: n/a
Keith Thompson wrote:
pete <pf*****@mindspring.comwrites:
>Simon Biber wrote:
>>void print_func(void (*p)())
{
unsigned char *a = (unsigned char *)&p;

That's undefined.
The standard doesn't describe what happens
when a function pointer is converted to an object pointer.

That's not what the code is trying to do. p is a function pointer,
but &p is an object pointer (it points to the function pointer). The
code, if I recall correctly, decomposes the representation of the
function pointer to a sequence of bytes to be printed. The results
are implementation-defined, but it's legal, and it's the only portable
way to print (a representation of) the value of a function pointer.
Amazingly enough, it works here, if you will put up with some digit
jumbling, and lack of knowledge of the size involved.

[1] c:\c\junk>cat junk.c
#include <stdio.h>

int return10(void) {return 10;}

int main(int argc, char ** argv)
{
int (*f)(void) = return10;
unsigned char *p = (unsigned char *)&f;
int i, n;
char hex[] = "0123456789abcdef";

for (i = 0; i < 4; i++) {
n = *(p + i);
putchar(hex[(n & 0xf0) >4]);
putchar(hex[(n & 0x0f)]);
}
putchar('\n');
return 0;
} /* main */

[1] c:\c\junk>cc junk.c
junk.c: In function `main':
junk.c:5: warning: unused parameter `argc'
junk.c:5: warning: unused parameter `argv'

[1] c:\c\junk>.\a
30160000

[1] c:\c\junk>objdump -dS a.exe | grep return10
00001630 <_return10>:
int return10(void) {return 10;}
int (*f)(void) = return10;

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Nov 3 '06 #32

P: n/a
CBFalconer wrote:
Keith Thompson wrote:
>That's not what the code is trying to do. p is a function pointer,
but &p is an object pointer (it points to the function pointer). The
code, if I recall correctly, decomposes the representation of the
function pointer to a sequence of bytes to be printed. The results
are implementation-defined, but it's legal, and it's the only portable
way to print (a representation of) the value of a function pointer.

Amazingly enough, it works here, if you will put up with some digit
jumbling, and lack of knowledge of the size involved.
The digit jumbling is due to little-endian representation. You can
reverse the bytes if the pointer value makes more sense to you that way.

There is no lack of knowledge of the size involved. You can get it from
sizeof. Either sizeof f, or sizeof (int(*)(void)).
[1] c:\c\junk>cat junk.c
#include <stdio.h>

int return10(void) {return 10;}

int main(int argc, char ** argv)
{
int (*f)(void) = return10;
unsigned char *p = (unsigned char *)&f;
int i, n;
i should be size_t
char hex[] = "0123456789abcdef";

for (i = 0; i < 4; i++) {
That should be
for (i = 0; i < sizeof f; i++) {
n = *(p + i);
putchar(hex[(n & 0xf0) >4]);
putchar(hex[(n & 0x0f)]);
}
putchar('\n');
return 0;
} /* main */
--
Simon.
Nov 3 '06 #33

P: n/a
pete:
> void (*const pfunc)(void) = hello;

char unsigned const *p = (char unsigned const*)&pfunc;

The standard doesn't provide a way to convert a function pointer
to an object pointer either.

Well then I guess I'm lucky I converted from "a pointer to a function
pointer", rather than just a plain old "function pointer". Contrast:

(char unsigned const*)&pfunc

with:

(char unsigned const*)pfunc

--

Frederick Gotham
Nov 3 '06 #34

P: n/a
Simon Biber wrote:
CBFalconer wrote:
>Keith Thompson wrote:
>>That's not what the code is trying to do. p is a function pointer,
but &p is an object pointer (it points to the function pointer). The
code, if I recall correctly, decomposes the representation of the
function pointer to a sequence of bytes to be printed. The results
are implementation-defined, but it's legal, and it's the only portable
way to print (a representation of) the value of a function pointer.

Amazingly enough, it works here, if you will put up with some digit
jumbling, and lack of knowledge of the size involved.

The digit jumbling is due to little-endian representation. You can
reverse the bytes if the pointer value makes more sense to you that way.
I didn't care. I just wanted to see if it extracted the function
address on my system.
There is no lack of knowledge of the size involved. You can get it from
sizeof. Either sizeof f, or sizeof (int(*)(void)).
I don't think so. A function pointer may be a large involved
thing, such as fields for segment, offset, in/out_ofmemory, etc. I
don't think sizeof can cope with this. At any rate I again didn't
care for this test.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Nov 3 '06 #35

P: n/a
CBFalconer <cb********@yahoo.comwrites:
Simon Biber wrote:
[...]
>There is no lack of knowledge of the size involved. You can get it from
sizeof. Either sizeof f, or sizeof (int(*)(void)).

I don't think so. A function pointer may be a large involved
thing, such as fields for segment, offset, in/out_ofmemory, etc. I
don't think sizeof can cope with this. At any rate I again didn't
care for this test.
Of course sizeof can cope with it. sizeof f, where f is an object of
a pointer-to-function type, gives you the size of the pointer object.
Obviously it won't tell you anything about what the representation
means, but that's not the point; it's enough to let you display the
representation.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 3 '06 #36

P: n/a
2006-11-03 <45***************@yahoo.com>,
CBFalconer wrote:
I don't think so. A function pointer may be a large involved
thing, such as fields for segment, offset, in/out_ofmemory, etc. I
don't think sizeof can cope with this. At any rate I again didn't
care for this test.
Wtf? sizeof is not limited to primitive types. You can take the sizeof
a struct type. or an array type. Even a struct or array containing
function pointers. Or an array of structs that contain arrays of
function pointers.
Nov 3 '06 #37

P: n/a
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
>Simon Biber wrote:
[...]
>>There is no lack of knowledge of the size involved. You can get
it from sizeof. Either sizeof f, or sizeof (int(*)(void)).

I don't think so. A function pointer may be a large involved
thing, such as fields for segment, offset, in/out_ofmemory, etc. I
don't think sizeof can cope with this. At any rate I again didn't
care for this test.

Of course sizeof can cope with it. sizeof f, where f is an object of
a pointer-to-function type, gives you the size of the pointer object.
Obviously it won't tell you anything about what the representation
means, but that's not the point; it's enough to let you display the
representation.
I stand corrected. If it ever comes up I may remember it. I doubt
it will come up.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Nov 4 '06 #38

P: n/a
An interesting topic indeed. Admittedly, Standard knowledge is not my
strong side, but what about the following (POSIX I think):

void *dlsym(void *restrict handle, const char *restrict name);

--- code ---
#include <dlfcn.h>
#include <stdio.h>

void
myfcn (void)
{
printf ("myfcn\n");
}

int
main (void)
{
void *ptr = dlsym (RTLD_DEFAULT, "myfcn");
printf ("ptr=%p\n", ptr);
printf ("myfcn ptr=%p\n", (void *)myfcn);

return 0;
}
--- code ---

Could dlsym() be considered a valid way of doing this? At least for the
POSIX-compliant compilers/systems?

--
WYCIWYG - what you C is what you get

Nov 4 '06 #39

P: n/a
2006-11-04 <11*********************@h54g2000cwb.googlegroups. com>,
ma*****@gmail.com wrote:
Could dlsym() be considered a valid way of doing this? At least for the
POSIX-compliant compilers/systems?
Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.
Nov 4 '06 #40

P: n/a
On Thu, 2 Nov 2006 19:10:50 UTC, Jordan Abel <ra****@random.yi.org>
wrote:
2006-11-02 <Si*****************@nnrp.ca.mci.com!nnrp1.uunet.c a>,
Clever Monkey wrote:
Default User wrote:
Richard Tobin wrote:

What are the two errors in the declaration of main()?
main() can be one of:

int main(void) { /* ... */ }

or

int main(int, char**) { /* ... */ }

I think this is documented in the section dealing with program startup.

Yeah, but I count one error, not two.

Unless you're saying all of the following are therefore invalid
int main() { }
int main(c,v) char **v; { }
Allowed in K&R C. tolerated in C89, illegal in C99.
main() { }
main(c,v) char **v; { }
illegal in C99.
main(void) { }
[and other combinations]
Depends on the standard you use for compile.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
Nov 5 '06 #41

P: n/a
On Sat, 4 Nov 2006 22:19:44 UTC, Jordan Abel <ra****@random.yi.org>
wrote:
2006-11-04 <11*********************@h54g2000cwb.googlegroups. com>,
ma*****@gmail.com wrote:
Could dlsym() be considered a valid way of doing this? At least for the
POSIX-compliant compilers/systems?

Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.
No. void* may even not wide enough to hold an address of a function.
Trying to convert a pointer to a function to anything else than to a
pointer to a function of same or another type is undefined behavior.
Like any undefined behavior it may work on your system but it may
result in flying demons out of your nose.

You can do with a function
- call it
- create a function pointer and assign its address to it
- create a function pointer to a function pointer and assign
the address of a function pointer to it - and so on.

You can't do without ending in the lands of undefined behavior:
- assign the address of a function to an pointer of any type that is
not a pointer to function
- convert a pointer to data to a pointer to function.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
Nov 5 '06 #42

P: n/a
In article <wm***************************@JUPITER1.PC-ROSENAU.DE>,
Herbert Rosenau <os****@pc-rosenau.dewrote:
>Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.
>No. void* may even not wide enough to hold an address of a function.
Then apparently such a system cannot support POSIX.
>Trying to convert a pointer to a function to anything else than to a
pointer to a function of same or another type is undefined behavior.
Undefined by C. But most systems don't only support C.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 5 '06 #43

P: n/a
"Herbert Rosenau" <os****@pc-rosenau.dewrites:
On Sat, 4 Nov 2006 22:19:44 UTC, Jordan Abel <ra****@random.yi.org>
wrote:
>2006-11-04 <11*********************@h54g2000cwb.googlegroups. com>,
ma*****@gmail.com wrote:
Could dlsym() be considered a valid way of doing this? At least for the
POSIX-compliant compilers/systems?

Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.

No. void* may even not wide enough to hold an address of a function.
Did you miss the "on a POSIX system" qualification?

The C standard doesn't require void* to be wide enough to hold the
address of a function. <OT>POSIX imposes additional requirement.</OT>

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 5 '06 #44

P: n/a
Herbert Rosenau wrote:
On Sat, 4 Nov 2006 22:19:44 UTC, Jordan Abel <ra****@random.yi.org>
wrote:
>2006-11-04 <11*********************@h54g2000cwb.googlegroups. com>,
ma*****@gmail.com wrote:
>>Could dlsym() be considered a valid way of doing this? At least for the
POSIX-compliant compilers/systems?
Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.

No. void* may even not wide enough to hold an address of a function.
Trying to convert a pointer to a function to anything else than to a
pointer to a function of same or another type is undefined behavior.
Like any undefined behavior it may work on your system but it may
result in flying demons out of your nose.
Read again what Jordan wrote. He was specifically talking about POSIX
systems or other systems that provide a POSIX like dlsym() function. On
such systems dlsym is defined (by the implementation) as returning a
function pointer but has a return type of void*. The POSIX standard, and
any other system providing a similar dlsym() function, therefore defines
a conversion between function pointers and void*. So on such a system
you *can* do the conversion in safety. On a system without dlsym you
could not use dlsym. So Jordan was correct to say that using dlsym() was
not really a work around because it would only work where you are
*guaranteed* by the implementation not to need it.

Implementations are specifically allowed to define anything the
implementation leaves (or specifies as) undefined behaviour.

As far as the C standard is concerned it is, of course, undefined.
However, the C standard does not define what happens if you call a
system provided dlsym function either.

There are, of course, solutions to the problem the OP had that do not
rely on things outside the C standard and these have been posted by
others already.
--
Flash Gordon
Nov 5 '06 #45

P: n/a
On Sun, 5 Nov 2006 10:02:30 UTC, ri*****@cogsci.ed.ac.uk (Richard
Tobin) wrote:
In article <wm***************************@JUPITER1.PC-ROSENAU.DE>,
Herbert Rosenau <os****@pc-rosenau.dewrote:
Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.
No. void* may even not wide enough to hold an address of a function.

Then apparently such a system cannot support POSIX.
Trying to convert a pointer to a function to anything else than to a
pointer to a function of same or another type is undefined behavior.

Undefined by C. But most systems don't only support C.
This group has nothing to do with any< system - it is related to C. So
saying this or that system is not related on something the standard
requires or defies as undefined is of no relevance at all.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
Nov 5 '06 #46

P: n/a
On Sun, 5 Nov 2006 10:21:58 UTC, Keith Thompson <ks***@mib.orgwrote:
"Herbert Rosenau" <os****@pc-rosenau.dewrites:
On Sat, 4 Nov 2006 22:19:44 UTC, Jordan Abel <ra****@random.yi.org>
wrote:
2006-11-04 <11*********************@h54g2000cwb.googlegroups. com>,
ma*****@gmail.com wrote:
Could dlsym() be considered a valid way of doing this? At least for the
POSIX-compliant compilers/systems?

Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.
No. void* may even not wide enough to hold an address of a function.

Did you miss the "on a POSIX system" qualification?
What has POSIX to do with the C standard?
The C standard doesn't require void* to be wide enough to hold the
address of a function. <OT>POSIX imposes additional requirement.</OT>
May be, may be not, bot this group has nothing to do with POSIX at
all. When POSIX is not standard compilant then it is completely off
topic here.
--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
Nov 5 '06 #47

P: n/a
"Herbert Rosenau" <os****@pc-rosenau.dewrites:
On Sun, 5 Nov 2006 10:21:58 UTC, Keith Thompson <ks***@mib.orgwrote:
>"Herbert Rosenau" <os****@pc-rosenau.dewrites:
On Sat, 4 Nov 2006 22:19:44 UTC, Jordan Abel <ra****@random.yi.org>
wrote:
2006-11-04 <11*********************@h54g2000cwb.googlegroups. com>,
ma*****@gmail.com wrote:
Could dlsym() be considered a valid way of doing this? At least for the
POSIX-compliant compilers/systems?

Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.

No. void* may even not wide enough to hold an address of a function.

Did you miss the "on a POSIX system" qualification?

What has POSIX to do with the C standard?
POSIX is based on the C standard.

<ON-TOPIC>
A secondary standard, or a particular implementation, is allowed to
impose additional requirements not imposed by the C standard itself.
In particular, it may define the behavior of constructs whose behavior
is undefined by the C standard. For example, a function that returns
a void* intended to be used as a function pointer cannot be portable,
but it can be specified by a secondary standard or by a particular
implementation. Any code that uses such a function is portable only
to that implementation, or to systems that support that secondary
standard.
</ON-TOPIC>

<OFF-TOPIC>
The dlsym() function specified by POSIX is an example of this.
</OFF-TOPIC>
>The C standard doesn't require void* to be wide enough to hold the
address of a function. <OT>POSIX imposes additional requirement.</OT>

May be, may be not, bot this group has nothing to do with POSIX at
all. When POSIX is not standard compilant then it is completely off
topic here.
I'm not convinced it's *completely* off-topic. I'd say it's topical
to the extent that it illustrates a point about extensions. The
standard explicitly permits extensions, after all.

But even if it's completely off-topic, it would have been better to
point out that it's off-topic rather than to pretend that the phrase
"on a POSIX system" wasn't there.

You response:

No. void* may even not wide enough to hold an address of a function.

is true in the context of standard C, but the question was clearly
limited to the context of POSIX systems. In effect, you responded to
an off-topic question with a response that was both off-topic and
incorrect.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 5 '06 #48

P: n/a
In article <wm***************************@JUPITER1.PC-ROSENAU.DE>,
Herbert Rosenau <os****@pc-rosenau.dewrote:
>Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.
>No. void* may even not wide enough to hold an address of a function.
>Then apparently such a system cannot support POSIX.
>Trying to convert a pointer to a function to anything else than to a
pointer to a function of same or another type is undefined behavior.
>Undefined by C. But most systems don't only support C.
>This group has nothing to do with any< system - it is related to C. So
saying this or that system is not related on something the standard
requires or defies as undefined is of no relevance at all.
Whether it's relevant is irrelevant to the fact that your statement
"No" is false, since the context was a POSIX system regardless of
what this group is about.

-- Richard

--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 5 '06 #49

P: n/a
2006-11-05 <wm***************************@JUPITER1.PC-ROSENAU.DE>,
Herbert Rosenau wrote:
On Sat, 4 Nov 2006 22:19:44 UTC, Jordan Abel <ra****@random.yi.org>
wrote:
>2006-11-04 <11*********************@h54g2000cwb.googlegroups. com>,
ma*****@gmail.com wrote:
Could dlsym() be considered a valid way of doing this? At least for the
POSIX-compliant compilers/systems?

Not really. on a POSIX system, or really anything that supports dlsym,
conversion between function pointers and void * is defined anyway.

No. void* may even not wide enough to hold an address of a function.
On a POSIX system, it is. It's in that _other_ standard, you know? So
using dlsym (which is the reason why POSIX requires it) trickery for
this purpose is beyond silly. Either it'll work or dlsym() won't.
Nov 6 '06 #50

54 Replies

This discussion thread is closed

Replies have been disabled for this discussion.