Call function address stored in type of size_t?

K

Keith Thompson

Mark McIntyre said:
Firstly the & is not neccessary - the name of a function is a pointer to
it.

More precisely, when a function name appears in an expression context,
it's implicitly converted to a pointer-to-function unless it's the
operand of a unary "&" or sizeof operator. (The latter results in a
constraint violation). Applying "&" to a function yields its address,
so inc and &inc are equivalent. The explicit "&" arguably makes it
clearer that you're taking the address of the function.

(This applies even on a function call; a function call operator's
first argument is a pointer-to-function.)
More importantly tho, since inc() is local to glfn1(), when you
return from glfn1, it disappears. Hence its address becomes invalid
and referencing it will probably cause a segfault. .

Maybe. The C standard says nothing about what happens to nested
functions when you leave the scope in which they're defined, since the
C standard says nothing about nested functions. The gcc documentation
will probably tell you more. <speculation>The code for the function
isn't going to go away, but the context for the call is going to be
gone; I don't know whether that's going to cause a segfault.
Conceivably there's no problem unless it makes uplevel references.
</speculation>
 
M

Mark McIntyre

Maybe. The C standard says nothing about what happens to nested
functions when you leave the scope in which they're defined, since the
C standard says nothing about nested functions.

It does however say what happens to local objects, and inc() is one of
those, more or less.
<speculation>The code for the function isn't going to go away,

It might - the compiler might do the same it does with local variables,
which /do/ 'go away' when the function ends.
 
K

Keith Thompson

Mark McIntyre said:
It does however say what happens to local objects, and inc() is one of
those, more or less.

No, inc is a function, not an object.
It might - the compiler might do the same it does with local variables,
which /do/ 'go away' when the function ends.

That hardly seems likely. The code for the function is presumably
compiled into the executable file, not allocated on the stack.

BTW, I just read the section of the gcc manual that deals with nested
functions. Anyone interested in the topic should do likewise (instead
of asking about it here).
 
M

Mark McIntyre

inc is a function, not an object.

hence the "more or less".... :)
The code for the function is presumably
compiled into the executable file, not allocated on the stack.

But then loaded into memory and executed. Once executed, why not unload it?
Its what many OSen would do with unused functions.
 
K

Keith Thompson

Mark McIntyre said:
hence the "more or less".... :)


But then loaded into memory and executed. Once executed, why not unload it?
Its what many OSen would do with unused functions.

I still think you're wrong, but the whole thing is off-topic.
(Notice how I cleverly get the last word.)
 
M

Michael Mair

Michael said:
full_struct isn't allowed to put any padding before its first member,
so a pointer to a full_struct can be cast to a pointer to a pub_struct
and safely dereferenced.

I might prefer, though, to rely on the "common initial members" rule,
and define them thus:

struct pub_data { /* public fields */ };
struct pub_struct { struct pub_data public; };
struct full_struct { struct pub_data public; int private; };

This has an advantage for maintenance: if at a later date you decide
you need more public members, you can create a new struct pub_data2,
put that after "public" in full_struct, and create a new struct
pub_struct2 to "publish" it - all without affecting existing code
that only needs to know about pub_data. (With your method, you'd be
changing the size of pub_struct if you added new public fields, for
example.)

Yep, that is true.
(Technically, I believe the standard says that accessing the common
initial members of one structure type through another structure type
is only guaranteed if they're in a union, but since it's tough for
the implementation to know whether they might be in one or not in
some TU, in practice it's probably fine to just cast pointers rather
than create a union purely for aliasing purposes.)

This is what I think, too, but it was the starting point for
my doubts whether the way I suggested is standard conforming.

However, it may be best simply to keep the entire thing opaque and
provide access functions. There's a performance tradeoff, but in
most cases it won't be important.

ACK.

Thank you very much for your reply!


Cheers
Michael
 
C

Chris Torek

[Some] may be interested in this reference I've just come across:

"Object-Oriented Programming in ANSI C"
by Axel-Tobias Schreiner (October 1993)

The first chapter is devoted to informing hiding in abstract data types.
The English translation is freely available as a PDF from the author:
<http://www.cs.rit.edu/~ats/>
<http://www.cs.rit.edu/~ats/books/index.html>
<http://www.cs.rit.edu/~ats/books/ooc.pdf>

I had a brief look at it, and it appears to make some nonportable
(and unnecessary) assumptions. The biggest (and perhaps only[%])
one is that "struct S *" and "void *" have the same underlying
storage size and/or representation.

C89 implies, and C99 requires, that "struct S *" and "struct T *"
have the same underlying storage sizes, at least, so the initial
"void *" pointers could be defined as pointers to a never-completed
structure type, and avoid the problem.
 

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
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top