473,324 Members | 2,473 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,324 software developers and data experts.

page 120 K&R

mdh
Hi All,
this little nonsense function is an attempt to understand function
pointers.

/*********/

#include <stdio.h>

void p(int);

int main (int argc, const char * argv[]) {
void (*q)(int) = p;
q(50); /* Question about this */
return 0;
}
void p(int i){

int j = i, k=1;

while ( i-- 0)
printf("Print me %d times (iteration %2d)\n", j, k++);
}

/*****/

From my reading on p 120 I expected the call to p to be *q(50) and not
q(50) but *q gives an error. Paraphrasing K&R, q is a pointer to a
function, *q is the function and (*q)( arguments) is the call to it.
Could someone explain what I am missing?
Thank you.

Nov 27 '07 #1
35 1969
On Nov 26, 10:02 pm, mdh <m...@comcast.netwrote:
Hi All,
this little nonsense function is an attempt to understand function
pointers.

/*********/

#include <stdio.h>

void p(int);

int main (int argc, const char * argv[]) {
void (*q)(int) = p;
q(50); /* Question about this */
return 0;

}

void p(int i){

int j = i, k=1;

while ( i-- 0)
printf("Print me %d times (iteration %2d)\n", j, k++);
}

/*****/

From my reading on p 120 I expected the call to p to be *q(50) and not
q(50) but *q gives an error. Paraphrasing K&R, q is a pointer to a
function, *q is the function and (*q)( arguments) is the call to it.
Could someone explain what I am missing?
C:\tmp>oops
entered p with 7
Print me 7 times (iteration 1)
Print me 7 times (iteration 2)
Print me 7 times (iteration 3)
Print me 7 times (iteration 4)
Print me 7 times (iteration 5)
Print me 7 times (iteration 6)
Print me 7 times (iteration 7)
entered p with 3
Print me 3 times (iteration 1)
Print me 3 times (iteration 2)
Print me 3 times (iteration 3)
entered p with 4
Print me 4 times (iteration 1)
Print me 4 times (iteration 2)
Print me 4 times (iteration 3)
Print me 4 times (iteration 4)

C:\tmp>type oops.c
#include <stdio.h>

void p(int);

int main(int argc, const char *argv[])
{
void (*q) (int) = p;
q(7);
(*q) (3);
p(4);
return 0;
}

void p(int i)
{
int j = i,
k = 1;
printf("entered %s with %d\n", __FUNCTION__, i);
while (i-- 0)
printf("Print me %d times (iteration %2d)\n", j, k++);
}

/*****/

Nov 27 '07 #2
mdh wrote, On 27/11/07 06:02:
Hi All,
this little nonsense function is an attempt to understand function
pointers.

/*********/

#include <stdio.h>

void p(int);

int main (int argc, const char * argv[]) {
void (*q)(int) = p;
q(50); /* Question about this */
<snip>
From my reading on p 120 I expected the call to p to be *q(50) and not
q(50) but *q gives an error. Paraphrasing K&R, q is a pointer to a
function, *q is the function and (*q)( arguments) is the call to it.
Could someone explain what I am missing?
You are missing a few things. The first is that in most situations the
name of a function "decays" to a function pointer (which is why you did
not need to use & to take the address of p) and when you are calling a
function you are actually calling it via the function pointer. Obviously
q is a function pointer so as calls are via function pointers you can
call through it.

Next is that () binds more tightly to q than *, to *q(50) means call q
passing 50 to it and dereference the (pointer) value returned by q,
which is obviously an error as q does not return any value, let alone a
pointer. So you need (*q)(50) to dereference q and then call the
function it points to. Even so this only works because of the strange
rules of C which mean that having dereferenced q it then gets
automatically converted back to a function pointer. As a side effect you
could just as well use (*******q)(50). It also makes applying & to a
function name pointless.
--
Flash Gordon
Nov 27 '07 #3
mdh
On Nov 27, 12:51 am, Flash Gordon <s...@flash-gordon.me.ukwrote:
mdh wrote, On 27/11/07 06:02:

int main (int argc, const char * argv[]) {
void (*q)(int) = p;
q(50); /* Question about this */

<snip>
>
You are missing a few things. The first is that in most situations the
name of a function "decays" to a function pointer (which is why you did
not need to use & to take the address of p) and when you are calling a
function you are actually calling it via the function pointer.
Let me make sure I understand you. Once a function is defined, the
address of that function becomes equivalent to it's name. So any
reference to that function is simply a reference to it's address.
(Kind of similar to the way an array is referenced?)

Next is that () binds more tightly to q than *, to *q(50) means call q
passing 50 to it and dereference the (pointer) value returned by q,
which is obviously an error

I keep getting tripped up by associativity....thank you.

as q does not return any value, let alone a
pointer. So you need (*q)(50) to dereference q and then call the
function it points to. Even so this only works because of the strange
rules of C which mean that having dereferenced q it then gets
automatically converted back to a function pointer.

Ok...thank you. One step closer to nirvana!!!
Nov 27 '07 #4
mdh
On Nov 26, 11:01 pm, user923005 <dcor...@connx.comwrote:
On Nov 26, 10:02 pm, mdh <m...@comcast.netwrote:
C:\tmp>oops
entered p with 7
Print me 7 times (iteration 1)
Print me 7 times (iteration 2)
Print me 7 times (iteration 3)
Print me 7 times (iteration 4)
Print me 7 times (iteration 5)
Print me 7 times (iteration 6)
Print me 7 times (iteration 7)
entered p with 3
Print me 3 times (iteration 1)
Print me 3 times (iteration 2)
Print me 3 times (iteration 3)
entered p with 4
Print me 4 times (iteration 1)
Print me 4 times (iteration 2)
Print me 4 times (iteration 3)
Print me 4 times (iteration 4)

C:\tmp>type oops.c
#include <stdio.h>

void p(int);

int main(int argc, const char *argv[])
{
void (*q) (int) = p;
q(7);
(*q) (3);
p(4);
return 0;

}

void p(int i)
{
int j = i,
k = 1;
printf("entered %s with %d\n", __FUNCTION__, i);
while (i-- 0)
printf("Print me %d times (iteration %2d)\n", j, k++);

}

/*****/

thank you
Nov 27 '07 #5
mdh wrote, On 27/11/07 09:21:
On Nov 27, 12:51 am, Flash Gordon <s...@flash-gordon.me.ukwrote:
>mdh wrote, On 27/11/07 06:02:
>>int main (int argc, const char * argv[]) {
void (*q)(int) = p;
q(50); /* Question about this */
<snip>
>You are missing a few things. The first is that in most situations the
name of a function "decays" to a function pointer (which is why you did
not need to use & to take the address of p) and when you are calling a
function you are actually calling it via the function pointer.

Let me make sure I understand you. Once a function is defined, the
address of that function becomes equivalent to it's name. So any
reference to that function is simply a reference to it's address.
(Kind of similar to the way an array is referenced?)
<snip>

Yes, I believe the times this does not happen are also the for arrays
and function names. Note that one difference is that an array name
"decays" to a pointer to its first element where as a function name
gives a pointer to the function as a whole, an important difference.
--
Flash Gordon
Nov 27 '07 #6
mdh
On Nov 27, 2:34 am, Flash Gordon <s...@flash-gordon.me.ukwrote:
Note that one difference is that an array name
"decays" to a pointer to its first element where as a function name
gives a pointer to the function as a whole, an important difference.

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?

Nov 27 '07 #7
mdh said:
On Nov 27, 2:34 am, Flash Gordon <s...@flash-gordon.me.ukwrote:
>Note that one difference is that an array name
"decays" to a pointer to its first element where as a function name
gives a pointer to the function as a whole, an important difference.


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.
What string is that? The first line of the function's C source code? But -
assuming for the moment that we're using a compiler rather than an
interpreter - the source code need no longer be visible by the time the
program is running. It might not even exist any more.

If that isn't the string you meant, what string did you mean?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 27 '07 #8
In article
<b8**********************************@e6g2000prf.g ooglegroups.com>, mdh
<md**@comcast.netwrote on Tuesday 27 Nov 2007 5:58 pm:
On Nov 27, 2:34 am, Flash Gordon <s...@flash-gordon.me.ukwrote:
>Note that one difference is that an array name
"decays" to a pointer to its first element where as a function name
gives a pointer to the function as a whole, an important difference.

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.
What string. The first string in the source code for the function. But
that is useless at runtime.

Under most computers a pointer to a function holds the address of the
first machine instruction for that function. So, in a way, it is
analogous to the case with arrays, where the array name "decays" to a
pointer to the address of it's first element.

In fact with a simple cast you can even treat an array like a function
and attempt to execute it or treat a function like an array and examine
it's data. Of course doing any of this falls outside the scope of the
standard and the operating system may prevent you from executing data.
As a guess, because there is not an easy way to indicate the terminal
element?
No. Usually code has no "terminal element". It continues until a jump
instruction or a halt instruction or a trap instruction or something
like that.

Nov 27 '07 #9
mdh
On Nov 27, 5:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
mdh said:
On Nov 27, 2:34 am, Flash Gordon <s...@flash-gordon.me.ukwrote:
Note that one difference is that an array name
"decays" to a pointer to its first element where as a function name
gives a pointer to the function as a whole, an important difference.
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.

What string is that?
The wrong string, I am rapidly deducing!! :-)

Seriously though, I was just trying to understand why a string array
would decay to a pointer to the first character, and a function
pointer decays to the whole function. I assumed that part of the
answer is that one is able to determine the termination of the string
array by the NULL character.I suppose in a function, one has an array
of character pointers, now that I think about it. But that does bring
one back to the original query of why the pointer type is one of
"pointer to whole-function"
Nov 27 '07 #10
mdh wrote:
On Nov 27, 5:32 am, Richard Heathfield <r...@see.sig.invalidwrote:
>mdh said:
>>On Nov 27, 2:34 am, Flash Gordon <s...@flash-gordon.me.ukwrote:
Note that one difference is that an array name
"decays" to a pointer to its first element where as a function name
gives a pointer to the function as a whole, an important difference.
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.
What string is that?

The wrong string, I am rapidly deducing!! :-)

Seriously though, I was just trying to understand why a string array
would decay to a pointer to the first character, and a function
pointer decays to the whole function. I assumed that part of the
answer is that one is able to determine the termination of the string
array by the NULL character.I suppose in a function, one has an array
of character pointers, now that I think about it. But that does bring
one back to the original query of why the pointer type is one of
"pointer to whole-function"

Because you can usefully do something with part of an array, but you
can't usefully do anything with part of a function - it's not really
decomposable.
Nov 27 '07 #11
mdh wrote:
....
Seriously though, I was just trying to understand why a string array
would decay to a pointer to the first character, and a function
pointer decays to the whole function. I assumed that part of the
answer is that one is able to determine the termination of the string
array by the NULL character.I suppose in a function, one has an array
of character pointers, now that I think about it. But that does bring
I get the impression that you think a function pointer points at an
in-memory copy of the source code for that function. This is generally
not the case. It might be true in an interpreted version of C, though
even then it's far more likely to point at some interpreter-specific
partially-compiled representation of the source code. However, in a
compiled version of C the function pointer typically points at the entry
point for a block of machine code.

The fundamental reason why a pointer to a function is only a pointer to
the entire function is that the only thing you can do with a pointer to
a function is call the the function. A function has no accessible parts.
Nov 27 '07 #12
mdh
On Nov 27, 5:59 am, James Kuyper <jameskuy...@verizon.netwrote:
>
The fundamental reason why a pointer to a function is only a pointer to
the entire function is that the only thing you can do with a pointer to
a function is call the the function. A function has no accessible parts.
Thank you...makes sense...I was trying to read to much into it...as
usual!!

Nov 27 '07 #13
Chris Dollin said:
Richard Heathfield wrote:
<snip>
>>
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?
Sometimes. :-)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 27 '07 #14
Chris Dollin wrote:
...
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 :)

--
Best regards,
Andrey Tarasevich
Nov 27 '07 #15
mdh wrote:
Flash Gordon <s...@flash-gordon.me.ukwrote:
>Note that one difference is that an array name
"decays" to a pointer to its first element where as a function name
gives a pointer to the function as a whole, an important difference.

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.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 27 '07 #16
mdh
mdh wrote:
Just curious. Why is it that the pointer to a function decays to a
pointer for the whole function....snip
Flash Gordon <s...@flash-gordon.me.ukwrote:
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.
Nov 27 '07 #17
CBFalconer wrote, On 27/11/07 21:28:
mdh wrote:
>Flash Gordon <s...@flash-gordon.me.ukwrote:
>>Note that one difference is that an array name
"decays" to a pointer to its first element where as a function name
gives a pointer to the function as a whole, an important difference.
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.
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.
--
Flash Gordon
Nov 28 '07 #18
CBFalconer wrote:
...
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]'...

--
Best regards,
Andrey Tarasevich
Nov 28 '07 #19
Andrey Tarasevich wrote:
Chris Dollin wrote:
>...
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 :)
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.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 28 '07 #20
Flash Gordon wrote:
>
.... 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>

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Nov 28 '07 #21
CBFalconer <cb********@yahoo.comwrites:
Flash Gordon wrote:
... 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>
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.)

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 28 '07 #22
Andrey Tarasevich wrote:
CBFalconer wrote:
...
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".
Nov 28 '07 #23
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
>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.)
<OT>
What happens if you take the address of a dynamically-linked function
before the first call to it?
</OT>
Nov 28 '07 #24
Philip Potter wrote:
Keith Thompson wrote:
>CBFalconer <cb********@yahoo.comwrites:
>>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.)

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

Nov 28 '07 #25
santosh wrote:
Philip Potter wrote:
><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.
I was thinking of situations where a function is loaded on first call; I
don't know if this is at all common.

Phil
Nov 28 '07 #26
Philip Potter wrote:
santosh wrote:
>Philip Potter wrote:
>><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.

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.

Nov 28 '07 #27
santosh wrote, On 28/11/07 16:53:
Philip Potter wrote:
>santosh wrote:
>>Philip Potter wrote:
<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.
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.
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.
--
Flash Gordon
Nov 28 '07 #28
ja*********@verizon.net wrote:
Andrey Tarasevich wrote:
>CBFalconer wrote:
...
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.

--
Best regards,
Andrey Tarasevich
Nov 29 '07 #29
In article <fi**********@aioe.orgPhilip Potter <pg*@doc.ic.ac.ukwrites:
santosh wrote:
Philip Potter wrote:
<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.

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.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Nov 29 '07 #30
Philip Potter <pg*@doc.ic.ac.ukwrites:
Keith Thompson wrote:
[...]
>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>
Um, you get its address.

If the function has already been loaded into memory, or at least into
the program's memory space, at program startup (as is usually the
case), then there's no problem. If not, and if a function pointer is
implemented as a table index, then the implementation could allocate a
table entry, with the information (invisible to the program) to be
filled in at the first call. Or the function could be loaded either
when it's first called or when its address is first taken.

Whatever the method, it's the implementation's responsibility to get
it right.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Looking for software development work in the San Diego area.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 29 '07 #31
Keith Thompson wrote:
Philip Potter <pg*@doc.ic.ac.ukwrites:
>Keith Thompson wrote:
[...]
>>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>

Um, you get its address.

If the function has already been loaded into memory, or at least into
the program's memory space, at program startup (as is usually the
case), then there's no problem. If not, and if a function pointer is
implemented as a table index, then the implementation could allocate a
table entry, with the information (invisible to the program) to be
filled in at the first call. Or the function could be loaded either
when it's first called or when its address is first taken.

Whatever the method, it's the implementation's responsibility to get
it right.
I agree entirely. I was trying to suggest an implementation which might
use an index into a table for a function pointer instead of a machine
address, without enough knowledge to explicitly state a given case.
Nov 29 '07 #32
On Tue, 27 Nov 2007 17:19:49 -0800, Keith Thompson <ks***@mib.org>
wrote:
CBFalconer <cb********@yahoo.comwrites:
<snip>
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.)
Original Tandem NonStop, still emulated on its Compaq^WHP successor
machines. The ISA was originally defined with call instructions having
a 9-bit index into a table (at the beginning of the code segment) of
almost 512 entries each containing a 16-bit instruction address.

This provided a minor gain in code compactness, and at the same time a
security feature: the OS kernel was simply another code segment, and
kernel calls were a variant call instruction with an index into the
system PEP table instead of the user one, so you couldn't jump into
the middle of a system routine. Moreover, the entries in the table
were grouped into privilege levels (using the first two table slots,
leaving only 510 real entries, hence my 'almost' above) and the CPU
would only raise the privilege level on a system call to those
procedures (= slots = indexes) marked to allow it, like the entry
'gates' in Multics; this meant that the OS segment could also contain
internal routines usable only when already in privileged state
(normally in system code, but see below), and (shared) utility
routines like atoi usable from either user or system code but
privileged only when called from privileged/system code.

Further, the same feature was applied to 'user' (really process) code
segments, so that a process with special privilege (only) could
effectively localize exercise of that privilege to certain procedures,
automatically. This was used with a message-passing OS that today
would be called microkernel -- when a user program does an I/O call,
it directly calls (as above) a small kernel routine that looks up the
fd (or name in some cases) and then sends the request as a message to
the _process_ handling that device -- one* process for each disk
drive, one for magtape, one for each comms line/protocol of which
historically Tandem supported a wide variety although nowadays
TCP/IP/Ethernet is dominant. That driver process code would include
privileged routines (per the PEP table) to do (only) the hardware I/O.
(* Actually driver processes were at least pairs for fault tolerance
and sometimes more for load balancing; but the point here is that they
were always a different process than the user process, with their own
code segment and thus PEP and procedure indexes.)

When this architecture needed to expand code space beyond one (plus)
16-bit segment, they added a second level of indirection. Instead of
call-normal and call-kernel, the two instructions were call-same-seg,
with a 9-bit index into PEP as above; and call-cross-seg, with a 9-bit
index into another (XEP) table with each entry containing a segment id
(including process/kernel) plus a 9-bit PEP index within that segment.

The 'dynamic call' instruction, used for C function-pointer calls,
(now) takes in effect a XEP entry -- 6-bit (or maybe now 7?) to select
process/kernel segment and 9-bit index within that segment.

- formerly david.thompson1 || achar(64) || worldnet.att.net
Dec 10 '07 #33
David Thompson wrote:
Keith Thompson <ks***@mib.orgwrote:
>CBFalconer <cb********@yahoo.comwrites:
<snip>
>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.)

Original Tandem NonStop, still emulated on its Compaq^WHP successor
....

I wrote exactly zero of what you quoted.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>

--
Posted via a free Usenet account from http://www.teranews.com

Dec 10 '07 #34
David Thompson wrote:
On Tue, 27 Nov 2007 17:19:49 -0800, Keith Thompson <ks***@mib.org>
wrote:
>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.)

Original Tandem NonStop, still emulated on its Compaq^WHP successor
machines. The ISA was originally defined with call instructions having
a 9-bit index into a table (at the beginning of the code segment) of
almost 512 entries each containing a 16-bit instruction address.
<huge snip>

Very interesting read. Nearly 10 years ago, I attended a NonStop Kernel
training course, which I guess was primary intended for Tandem
employees. Nonetheless, it was one of the most interesting CS classes I
have taken.

One of the really nice things on this OS, was the message passing
architecture, combined with a pathway (monitor process), which made
server programming easy. No need for multi-threading.

Did you work on the NSK kernel group?

--
Tor <bw****@wvtqvm.vw | tr i-za-h a-z>
Dec 10 '07 #35
On Tue, 11 Dec 2007 00:30:37 +0100, Tor Rustad
<to********@hotmail.comwrote:
David Thompson wrote:
Original Tandem NonStop, still emulated on its Compaq^WHP successor
machines. The ISA was originally defined with call instructions having
a 9-bit index into a table (at the beginning of the code segment) of
almost 512 entries each containing a 16-bit instruction address.

<huge snip>

Very interesting read. Nearly 10 years ago, I attended a NonStop Kernel
training course, which I guess was primary intended for Tandem
employees. Nonetheless, it was one of the most interesting CS classes I
have taken.

One of the really nice things on this OS, was the message passing
architecture, combined with a pathway (monitor process), which made
server programming easy. No need for multi-threading.
I described (in the snip) the message-passing within the O/S (or at
least the most visible part of it, I/O); the use of (almost) the same
capability at user/application level was indeed another valuable and
unusual feature, but one whose description seemed to me to go even
further offtopic so I stopped. You may have noticed that I mentioned
fault-tolerance only briefly, although that was the primary purpose
for most of the architecture, including message-passing.

'Pathway' (or more precisely now TS/MP, if they haven't renamed it
again) + singlethread contextfree servers is convenient for _modest_
levels of concurrency. When you reach many thousands of small/brief
operations per second, or substantial numbers (say hundreds) of
long-running operations, you need to reintroduce some kind of
threading, although it may be via things like 'work queue' files.
Did you work on the NSK kernel group?
I didn't work for Tandeml, but for an outside 'third-party' software
developer; I just RTFMed -- a lot. (Aside: In those days it wasn't
'NSK', just Guardian and Guardian kernel; the distinction into NSK was
created later when they wanted to add POSIX support. Shortly before
the first=Compaq acquisition, IIRC.)

- formerly david.thompson1 || achar(64) || worldnet.att.net
Dec 24 '07 #36

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

Similar topics

6
by: adnanx82 | last post by:
Hi, I was wondering if anyone knew how to perform the following 2 tasks in Javascript: 1) distinguish between frames and iframes (during an onload event for example) 2) figure out whether a...
14
by: GabrielESandoval | last post by:
I need to make a registration page for a community service volleyball tournament our organization is doing. I am VERY NEW to ASP. Would the easiest way to make it be just doing it on frontpage...
7
by: GaryDean | last post by:
In my old 1.1 apps the default was MS_POSITIONING="GridLayout" and Textboxes and labels and such always had POSITION: absolute; and I never had any distortion when the page was rendered. Life was...
1
by: incognito | last post by:
Hello I recently started up my own website and aquired an affiliates directory script. Where webmasters can add thier site to my directory and visitors can rate the sites listed. All has been going...
3
by: DVir | last post by:
I am having problem with IE. This is the code that I am using, and it works good in every browser except in IE. If somebody can help PLEASE: <script language="Javascript" type="text/javascript">...
5
by: smittie31 | last post by:
I am having a problem with a border around me html page. The border does not flow thru the whole html page, it cuts off halfway. --> See http://keithborom.com/marlon-sanders CSS STYLESHEET ...
0
by: seanalex | last post by:
Hi All, I have a problem with one page in one client site. The page downloads to just before the end tag of the viewstate and then stops. Most of the time it won't do anything after that, but...
3
by: hsahealthsavings | last post by:
I made this page using a free html editor called formbreeze. The issue is 1) There is a whole bunch of white space at the end of the page that I cannot seem to figure how to get rid of 2) I have...
10
by: jollysr | last post by:
Could someone please help me convert the following XML to HTML page? <?xml version="1.0" encoding="UTF-16"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.