page 120 K&R

C

Chris Dollin

Richard said:
Chris Dollin said:


Very true.

Alas, we don't always write small functions, do we?

Perhaps not always (he said, remembering the 800-line monster) -- but
usually, yes.
Much as we might intend to.

And when it turns out that we lose track of names within that function,
we carve it up into legible pieces, don't we?
 
J

Jean-Marc Bourguet

Richard Heathfield said:
Chris Dollin said:


Very true.

Alas, we don't always write small functions, do we? Much as we might intend
to.

Functions are written small... and then some grow too much before
refactoring take place.
 
R

Richard Heathfield

Chris Dollin said:
Richard Heathfield wrote:


Perhaps not always (he said, remembering the 800-line monster) -- but
usually, yes.


And when it turns out that we lose track of names within that function,
we carve it up into legible pieces, don't we?

Sometimes. :)
 
F

Flash Gordon

Richard Heathfield wrote, On 27/11/07 13:29:
Flash Gordon said:


On re-reading, I discover that you're right, although I had to think about
it and read it very carefully to determine this. I apologise for
attempting to complete the complete. :)

Think of it as clarification instead of completion. If you had to think
hard about it then that point was probably not clear enough.
Yes, that's certainly true. Nevertheless, by using the indirection syntax,
we (might) save them the trouble of searching in the first place.

I have to say that in all of the instances where I have used variable of
function pointer type it has been either clear from context that it
would be a function pointer or it has been none of the callers business
that it is not actually the function (yes, there is a specific reason in
a library I use to be able to replace the called function behind the
application programmers back, and no it is not my design).
 
A

Andrey Tarasevich

Chris said:
...
And when it turns out that we lose track of names within that function,
we carve it up into legible pieces, don't we?
...

In 9 cases out of 10 "losing track of names within function" is a
consequence of the devastatingly bad, but still widely used practice of
declaring all names at the very beginning of the function. Even in
C89/90 it was possible to declare names close to the point where they
are used, not even mentioning C99.

Small functions are overrated :)
 
C

CBFalconer

mdh said:
Just curious. Why is it that the pointer to a function decays to a
pointer for the whole function vs the address of the first ?string.
As a guess, because there is not an easy way to indicate the
terminal element?

The function pointer doesn't point to the "whole function". In
practice, it actually points to the first executable instruction
within the function. The function then runs until it exits, with
some sort of return instruction. The call instruction (which
exists in the machine, but not in C) may do some sort of gyrations,
such as setting up a stack frame, etc.
 
C

CBFalconer

Andrey said:
In 9 cases out of 10 "losing track of names within function" is a
consequence of the devastatingly bad, but still widely used
practice of declaring all names at the very beginning of the
function. Even in C89/90 it was possible to declare names close
to the point where they are used, not even mentioning C99.

Small functions are overrated :)

When you keep the line count per function down to about twenty, and
the local variables (including parameters) referenced under about
seven, and avoid globals, all declarations seem to be pretty close
to the point of use.

The exception is big long dreary switch calls.
 
F

Flash Gordon

CBFalconer wrote, On 27/11/07 21:28:
The function pointer doesn't point to the "whole function". In
practice, it actually points to the first executable instruction
within the function.

As far as the standard is concerned it points to the function, the
standard does not mention the first executable instruction with the
function.
The function then runs until it exits, with
some sort of return instruction. The call instruction (which
exists in the machine, but not in C) may do some sort of gyrations,
such as setting up a stack frame, etc.

The C abstract machine also has some hoops to jump through, namely
converting the pointer to the function to a function designator.
However, all of these hoops (and I've interfaced assembler with a few
languages including C so I know a bit about how function calls work) are
irrelevant to the point. You cannot increment a function pointer to get
a pointer to some later point in the function, you can increment a
pointer to the first element of an array, and this distinction is important.
 
M

mdh

The function pointer doesn't point to the "whole function". In
practice, it actually points to the first executable instruction
within the function. The function then runs until it exits, with
some sort of return instruction. The call instruction (which
exists in the machine, but not in C) may do some sort of gyrations,
such as setting up a stack frame, etc.

Thanks....I like that sort of explanation.
 
A

Andrey Tarasevich

CBFalconer said:
...
The function pointer doesn't point to the "whole function". In
practice, it actually points to the first executable instruction
within the function. The function then runs until it exits, with
some sort of return instruction. The call instruction (which
exists in the machine, but not in C) may do some sort of gyrations,
such as setting up a stack frame, etc.
...

Well, it all depends on how you define the concept of "pointing to
something". Does a pointer of type 'int (*)[10]' point to the entire
array 'a' of type 'int[10]' or only to its first element? After all, "in
practice" its numerical value is the same as that of the pointer of type
'int*' pointing to 'a[0]'...
 
C

CBFalconer

.... snip on function pointers ...
The C abstract machine also has some hoops to jump through, namely
converting the pointer to the function to a function designator.
However, all of these hoops (and I've interfaced assembler with a
few languages including C so I know a bit about how function calls
work) are irrelevant to the point. You cannot increment a function
pointer to get a pointer to some later point in the function, you
can increment a pointer to the first element of an array, and this
distinction is important.

Yes, they can be incremented. I have done it often, but not in C.
:) If instructions are one byte (C bytes) long, then the
increment will normally access the next instruction. If not, very
peculiar things can happen.

You can also increment (and decrement) return addresses. <grin>
 
K

Keith Thompson

CBFalconer said:
Flash Gordon wrote:
... snip on function pointers ...

Yes, they can be incremented. I have done it often, but not in C.
:) If instructions are one byte (C bytes) long, then the
increment will normally access the next instruction. If not, very
peculiar things can happen.

You can also increment (and decrement) return addresses. <grin>

Well, in terms of C (this is comp.lang.c, after all), I'm afraid the
above is nonsense. Attempting to increment a function pointer is a
constraint violation, requiring a diagnostic. Attempting to increment
a return address doesn't even make sense, since return addresses
aren't directly accessible in C.

A function pointer needn't even be a machine address. It could, for
example, simply be an index into a table. (I don't know of any
implementations that do this.)
 
J

jameskuyper

Andrey said:
CBFalconer said:
...
The function pointer doesn't point to the "whole function". In
practice, it actually points to the first executable instruction
within the function. The function then runs until it exits, with
some sort of return instruction. The call instruction (which
exists in the machine, but not in C) may do some sort of gyrations,
such as setting up a stack frame, etc.
...

Well, it all depends on how you define the concept of "pointing to
something". Does a pointer of type 'int (*)[10]' point to the entire
array 'a' of type 'int[10]' or only to its first element? After all, "in
practice" its numerical value is the same as that of the pointer of type
'int*' pointing to 'a[0]'...

When you apply the dereferencing operator * to a pointer, what you
get is what it pointed at. If you have

int a[10];
int (*p)[10] = a;

Then what *p gives you is an array of 10 ints; which, in most
contexts, decays to a pointer to the first int in that array, but that
doesn't mean that p itself points at an 'int'.
I assume that what you mean by "numerical value" is the value you get
when you convert a pointer to intptr_t? If so, keep in mind that
there's no requirement that p and &a[0] have the same "numerical
value".
 
P

Philip Potter

Keith said:
Well, in terms of C (this is comp.lang.c, after all), I'm afraid the
above is nonsense. Attempting to increment a function pointer is a
constraint violation, requiring a diagnostic. Attempting to increment
a return address doesn't even make sense, since return addresses
aren't directly accessible in C.

A function pointer needn't even be a machine address. It could, for
example, simply be an index into a table. (I don't know of any
implementations that do this.)

<OT>
What happens if you take the address of a dynamically-linked function
before the first call to it?
</OT>
 
S

santosh

Philip said:
<OT>
What happens if you take the address of a dynamically-linked function
before the first call to it?
</OT>

Why? What should happen? Typically the address is going to be resolved
and patched in by the program loader, so by the time the C program
takes the address of a function (dynamically or statically linked), it
going to be a valid value.
 
P

Philip Potter

santosh said:
Why? What should happen? Typically the address is going to be resolved
and patched in by the program loader, so by the time the C program
takes the address of a function (dynamically or statically linked), it
going to be a valid value.

I was thinking of situations where a function is loaded on first call; I
don't know if this is at all common.

Phil
 
S

santosh

Philip said:
I was thinking of situations where a function is loaded on first call;
I don't know if this is at all common.

I think the loader should still place the address for the function into
your pointer before program start-up.
 
F

Flash Gordon

santosh wrote, On 28/11/07 16:53:
I think the loader should still place the address for the function into
your pointer before program start-up.

It has to allocate the address in time for it to be taken if it is taken
since in C you are allowed to take any functions address before calling it.
 
A

Andrey Tarasevich

Andrey said:
CBFalconer said:
...
The function pointer doesn't point to the "whole function". In
practice, it actually points to the first executable instruction
within the function. The function then runs until it exits, with
some sort of return instruction. The call instruction (which
exists in the machine, but not in C) may do some sort of gyrations,
such as setting up a stack frame, etc.
...

Well, it all depends on how you define the concept of "pointing to
something". Does a pointer of type 'int (*)[10]' point to the entire
array 'a' of type 'int[10]' or only to its first element? After all, "in
practice" its numerical value is the same as that of the pointer of type
'int*' pointing to 'a[0]'...

When you apply the dereferencing operator * to a pointer, what you
get is what it pointed at. If you have

int a[10];
int (*p)[10] = a;

int (*p)[10] = &a;
Then what *p gives you is an array of 10 ints; which, in most
contexts, decays to a pointer to the first int in that array, but that
doesn't mean that p itself points at an 'int'.

That's all great, but sounds like an answer to a question nobody really
asked. Apparently previous poster has a different view on this subject
(at least within the context of the post quoted above). I personally
prefer to perceive 'int (*)[10]' pointers as pointing to arrays, just
like I prefer to think of 'void (*)(void)' pointers as pointing to
functions, not to their "first executable instructions".
I assume that what you mean by "numerical value" is the value you get
when you convert a pointer to intptr_t? If so, keep in mind that
there's no requirement that p and &a[0] have the same "numerical
value".

There's no axiomatic requirement in the language specification. However,
my statement was made within the bounds of "practical" context set up by
the previous poster.
 
D

Dik T. Winter

>
> I was thinking of situations where a function is loaded on first call; I
> don't know if this is at all common.

I know of a system where that could be done. In that case the loader
resolved the reference to a weak reference, using a look-up table to
find the actual reference, which was marked empty until the function
was loaded. So the address would be the weak reference.
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,049
Members
48,769
Latest member
Clifft

Latest Threads

Top