get the address of a function??

C

Clever Monkey

Default said:
Richard said:
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.
 
J

Jordan Abel

2006-11-02 said:
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]
 
W

Walter Roberson

Clever Monkey said:
main() can be one of:
int main(void) { /* ... */ }

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().
 
C

Clever Monkey

Walter said:
Clever Monkey said:
main() can be one of:
int main(void) { /* ... */ }

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".
 
J

Jordan Abel

2006-11-02 said:
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.
 
K

Keith Thompson

Jordan Abel said:
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.
 
P

pete

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.
 
P

pete

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.
 
K

Keith Thompson

pete said:
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.
 
P

pete

pete said:
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.
 
P

pete

Keith said:
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.
 
C

CBFalconer

Keith said:
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;
 
S

Simon Biber

CBFalconer said:
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 */
 
F

Frederick Gotham

pete:
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
 
C

CBFalconer

Simon said:
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.
 
K

Keith Thompson

CBFalconer said:
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.
 
J

Jordan Abel

2006-11-03 said:
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.
 
C

CBFalconer

Keith said:
CBFalconer said:
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.
 
M

matevzb

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?
 
J

Jordan Abel

2006-11-04 <[email protected]>,
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top