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

A function is an address

P: n/a
Ignoring implementation details and strictly following the C99
standard in terms of semantics, is there anything fundamentally flawed
with describing the use of a (non-inline) function as an address[1]? I
keep feeling like I'm missing something obvious.
-Jul

[1] To keep things in context, this is in reference to describing
functions to a beginner.
Dec 7 '07 #1
Share this Question
Share on Google+
36 Replies


P: n/a
Julienne Walker wrote:
Ignoring implementation details and strictly following the C99
standard in terms of semantics, is there anything fundamentally flawed
with describing the use of a (non-inline) function as an address[1]? I
keep feeling like I'm missing something obvious.
It would probably be better to describe a function as
a custard pie.
-Jul

[1] To keep things in context, this is in reference to describing
functions to a beginner.
Oh, a beginner? In that case, "custard pie" is by far
the best way to introduce the topic. Later, when the pupil
has gained some understanding and experience, you can go
back and explain that "custard pie" is really a simplification;
in full generality a function can be any kind of dessert or
comedic prop whatsoever.

(In other words, have you taken leave of your senses,
or have they taken leave of you? Or are you a disciple of
Humpty Dumpty, determined to make words mean whatever you
want them to and without regard to what others may think
they mean?)

--
Er*********@sun.com
Dec 7 '07 #2

P: n/a
Julienne Walker wrote:
Ignoring implementation details and strictly following the C99
standard in terms of semantics, is there anything fundamentally flawed
with describing the use of a (non-inline) function as an address[1]? I
keep feeling like I'm missing something obvious.
A function typically has an associated memory address indicating the
entry point for the function. A function is not an address, any more
than your house is an address.
Dec 7 '07 #3

P: n/a
Julienne Walker <ha*********@hotmail.comwrites:
Ignoring implementation details and strictly following the C99
standard in terms of semantics, is there anything fundamentally flawed
with describing the use of a (non-inline) function as an address[1]? I
keep feeling like I'm missing something obvious.

[1] To keep things in context, this is in reference to describing
functions to a beginner.
I can't think of anything *not* fundamentally flawed about describing
the use of a function as an address.

I suspect what you're thinking of is the fact that an expression of
function type (including the name of a function) is, unless it's the
operand of a unary "sizeof" or "&" operator, implicitly converted to
the function's address, and the first operand of a function call
operator is actually a pointer-to-function, not necessarily a
function. I'm sure this is covered in the FAQ.

But this does not imply that a function *is* an address (it isn't),
and it's not necessarily something I'd mention to beginners.

Until a beginner starts to use function pointers explicitly, it
probably sufices to say that a function call func(arg1, arg2) calls
the specified function and passes it the specified arguments. The
fact that there's a conversion to a function pointer happening behind
the scenes can probably wait until later.

--
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"
Dec 7 '07 #4

P: n/a
Julienne Walker <ha*********@hotmail.comwrites:
[SNIP]
So please allow me to refine my question: In what cases would the use
of a function name *not* evaluate to a pointer to that function?
When it's the operand of a unary "sizeof" operator (which is a
constraint error, rather than yielding the size of a function
pointer), and when it's the operand of a unary "&" operator (which
yields the address of the function, rather than attempting to compute
the address of the address of the function, which would be a
constraint violation).

Note that this applies to any expression of function type, not just a
function name. For example, if ``p'' is an object of
pointer-to-function type, then ``*p'' is an expression of function
type, which then decays (back) to a pointer to the function.

It's quite similar to the hanlding of array names.

--
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"
Dec 7 '07 #5

P: n/a
>>>>"JW" == Julienne Walker <ha*********@hotmail.comwrites:

JWSo please allow me to refine my question: In what cases would
JWthe use of a function name *not* evaluate to a pointer to that
JWfunction?

Why does a beginner care?

Have you ever tried to teach programming before? This is a concept
that beginners simply do not need to worry about, and making the
beginners worry about it when you introduce functions is a damn fine
way to confuse them.

Charlton


--
Charlton Wilbur
cw*****@chromatico.net
Dec 7 '07 #6

P: n/a
On Dec 7, 4:49 pm, Keith Thompson <ks...@mib.orgwrote:
Julienne Walker <happyfro...@hotmail.comwrites:

[SNIP]
So please allow me to refine my question: In what cases would the use
of a function name *not* evaluate to a pointer to that function?

When it's the operand of a unary "sizeof" operator (which is a
constraint error, rather than yielding the size of a function
pointer), and when it's the operand of a unary "&" operator (which
yields the address of the function, rather than attempting to compute
the address of the address of the function, which would be a
constraint violation).

Note that this applies to any expression of function type, not just a
function name. For example, if ``p'' is an object of
pointer-to-function type, then ``*p'' is an expression of function
type, which then decays (back) to a pointer to the function.

It's quite similar to the hanlding of array names.

--
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"
Thank you. That's what I thought, but a worry kept tickling the back
of my brain that there was something else.
-Jul
Dec 7 '07 #7

P: n/a
ja*********@verizon.net writes:
[...]
A function name names a function, it is not the same thing as the
function itself. A function pointer will typically contain an address,
but a function pointer is not an address. A function name will decay
into a function pointer in almost every context, but a function name
is not a function pointer.
[...]

Actually, a function pointer *is* an address; it's the address of the
function. (The standard uses the words "address" and "pointer" almost
interchangeably.)

--
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"
Dec 7 '07 #8

P: n/a
On Dec 7, 4:40 pm, Charlton Wilbur <cwil...@chromatico.netwrote:
>>>"JW" == Julienne Walker <happyfro...@hotmail.comwrites:

JWSo please allow me to refine my question: In what cases would
JWthe use of a function name *not* evaluate to a pointer to that
JWfunction?

Why does a beginner care?
A beginner doesn't care about this exact detail, but I'm intending to
use it to smooth the entire process of learning C. Rest assured that
I'm not going to tell a beginner something like that without a plan.
Have you ever tried to teach programming before?
Yes.
This is a concept
that beginners simply do not need to worry about, and making the
beginners worry about it when you introduce functions is a damn fine
way to confuse them.
I appreciate your concern, but I don't think you're in a position to
make that judgment given nothing more than a quick question from me to
the experts on clc.
Charlton

--
Charlton Wilbur
cwil...@chromatico.net
Dec 7 '07 #9

P: n/a
Keith Thompson wrote:
ja*********@verizon.net writes:
[...]
A function name names a function, it is not the same thing as the
function itself. A function pointer will typically contain an address,
but a function pointer is not an address. A function name will decay
into a function pointer in almost every context, but a function name
is not a function pointer.
[...]

Actually, a function pointer *is* an address; it's the address of the
function. (The standard uses the words "address" and "pointer" almost
interchangeably.)
I think that, to the extent that the standard does so, it is
defective. Treating the two terms as interchangeable would, if
normative, prohibit the implementation of pointers as structures which
contain, among other things, the address of the location in memory
that they point at. I doubt that it was the intent of the committee to
prohibit such fat-pointer implementations.

Cross-posting to comp.std.c
Dec 7 '07 #10

P: n/a
Julienne Walker wrote:
[...]
So please allow me to refine my question: In what cases would the use
of a function name *not* evaluate to a pointer to that function?
Keith Thompson mentioned the curious case of `& fname',
and there's an equally curious `(*fname)'. With those
exceptions, I can think of no valid uses of function names
in expressions that do not evaluate to pointers to the
named functions.

Non-expression uses do not evaluate to anything at all:

int func(void); /* declares func, evaluates nothing */

void gunk(int) {} /* defines and declares gunk,
* evaluates nothing */

However, as you're talking to a beginner I'd suggest that
you not speak about "function pointers" or "function addresses"
at all. A function name is a name for a bunch of code that
expresses a bunch of operations to be performed, and there's
no need to fret about the details of how the machine represents
those operations. You don't need to talk about "instructions"
or "instruction addresses" or any such; the beginner should be
more concerned with the idea that a piece of code "here" can
somehow use a different piece of code "there," and with the
mechanics of passing arguments and returning values. That
is, concentrate on what a function does and not on how some
machine happens to do it.

... and if you want to use custard_pie() as a function
name, that's fine with me.

--
Er*********@sun.com
Dec 7 '07 #11

P: n/a
ja*********@verizon.net writes:
Keith Thompson wrote:
>ja*********@verizon.net writes:
[...]
A function name names a function, it is not the same thing as the
function itself. A function pointer will typically contain an address,
but a function pointer is not an address. A function name will decay
into a function pointer in almost every context, but a function name
is not a function pointer.
[...]

Actually, a function pointer *is* an address; it's the address of the
function. (The standard uses the words "address" and "pointer" almost
interchangeably.)

I think that, to the extent that the standard does so, it is
defective. Treating the two terms as interchangeable would, if
normative, prohibit the implementation of pointers as structures which
contain, among other things, the address of the location in memory
that they point at. I doubt that it was the intent of the committee to
prohibit such fat-pointer implementations.

Cross-posting to comp.std.c
Not at all. In an implementation with fat pointers, a fat pointer
*is* an address. For example, the unary "&" operator yields a fat
pointer value, which is the address of the operand.

--
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"
Dec 8 '07 #12

P: n/a
>>>>"J" == Julienne Walker <ha*********@hotmail.comwrites:
>This is a concept that beginners simply do not need to worry
about, and making the beginners worry about it when you
introduce functions is a damn fine way to confuse them.
JI appreciate your concern, but I don't think you're in a
Jposition to make that judgment given nothing more than a quick
Jquestion from me to the experts on clc.

On the contrary; I think, as one of those experts with some teaching
experience, I'm in an excellent position to judge that.

But carry on; thoroughly confusing beginners is a fine way to make
sure the consulting rates for competent C programmers remain high.

Charlton

--
Charlton Wilbur
cw*****@chromatico.net
Dec 8 '07 #13

P: n/a
Keith Thompson wrote:
ja*********@verizon.net writes:
>Keith Thompson wrote:
>>ja*********@verizon.net writes:
[...]
A function name names a function, it is not the same thing as the
function itself. A function pointer will typically contain an address,
but a function pointer is not an address. A function name will decay
into a function pointer in almost every context, but a function name
is not a function pointer.
[...]

Actually, a function pointer *is* an address; it's the address of the
function. (The standard uses the words "address" and "pointer" almost
interchangeably.)
I think that, to the extent that the standard does so, it is
defective. Treating the two terms as interchangeable would, if
normative, prohibit the implementation of pointers as structures which
contain, among other things, the address of the location in memory
that they point at. I doubt that it was the intent of the committee to
prohibit such fat-pointer implementations.

Cross-posting to comp.std.c

Not at all. In an implementation with fat pointers, a fat pointer
*is* an address. For example, the unary "&" operator yields a fat
pointer value, which is the address of the operand.
No, it isn't an address, it contains an address. It also contains other
things: bound's checking data, or type info, or a reference count, or
something else entirely, depending upon what kind of fat pointer it is.
Dec 8 '07 #14

P: n/a
On Dec 7, 12:28 pm, Julienne Walker <happyfro...@hotmail.comwrote:
Ignoring implementation details and strictly following the C99
standard in terms of semantics, is there anything fundamentally flawed
with describing the use of a (non-inline) function as an address[1]? I
keep feeling like I'm missing something obvious.
We reference a function by its address. A function is no more its
address than an array is its address. It's simply a handy handle we
have to reference it with.
We can use a function pointer and a function interchangably on
invocation, so there is no real important difference there.
A function address is different from a data address. Despite the fact
that it sometimes works, we are not supposed to store function
addresses in void pointers.
So the address of a function is a special sort of address.

Dec 8 '07 #15

P: n/a
Julienne Walker <happyfro...@hotmail.comwrote:
Ignoring implementation details and strictly following
the C99 standard in terms of semantics, is there anything
fundamentally flawed with describing the use of a (non-
inline) function as an address[1]? I keep feeling like
I'm missing something obvious.
Leave 'address' out of it. Just say that all functions are
called through function pointers and that names of functions
decay to function pointers in general expressions, except
in the case of sizeof.

--
PEter
Dec 8 '07 #16

P: n/a
James Kuyper <ja*********@verizon.netwrites:
Keith Thompson wrote:
>ja*********@verizon.net writes:
>>Keith Thompson wrote:
ja*********@verizon.net writes:
[...]
A function name names a function, it is not the same thing as the
function itself. A function pointer will typically contain an address,
but a function pointer is not an address. A function name will decay
into a function pointer in almost every context, but a function name
is not a function pointer.
[...]

Actually, a function pointer *is* an address; it's the address of the
function. (The standard uses the words "address" and "pointer" almost
interchangeably.)
I think that, to the extent that the standard does so, it is
defective. Treating the two terms as interchangeable would, if
normative, prohibit the implementation of pointers as structures which
contain, among other things, the address of the location in memory
that they point at. I doubt that it was the intent of the committee to
prohibit such fat-pointer implementations.

Cross-posting to comp.std.c

Not at all. In an implementation with fat pointers, a fat pointer
*is* an address. For example, the unary "&" operator yields a fat
pointer value, which is the address of the operand.

No, it isn't an address, it contains an address. It also contains
other things: bound's checking data, or type info, or a reference
count, or something else entirely, depending upon what kind of fat
pointer it is.
You're using the word "address" in a manner that's inconsistent with
the way the standard uses the word. There are other valid meanings of
the word, but they're no more relevant here than the common meaning of
"byte" as exactly 8 bits.

C99 65.3.2p3:

The unary & operator yields the address of its operand.

This address may or may not be a machine address.

--
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"
Dec 8 '07 #17

P: n/a
Julienne Walker wrote:
So please allow me to refine my question: In what cases would the use
of a function name *not* evaluate to a pointer to that function?
There are exactly two cases where
a function name will *not* evaluate to a pointer to that function:
1 As an operand of &
2 As an operand of sizeof

When the & operator is applied to an expression of function type,
the result is the address of the function.

sizeof is only defined for object types.
Since function type expressions
don't convert as operands of sizeof,
expressions with sizeof operating
on an expressions of function types, are undefined.

The only thing that you can do with an expression of function type,
in a correct C program, is to derive an address from it.

--
pete
Dec 8 '07 #18

P: n/a
Keith Thompson wrote:
James Kuyper <ja*********@verizon.netwrites:
>Keith Thompson wrote:
>>ja*********@verizon.net writes:
Keith Thompson wrote:
....
>>>>function. (The standard uses the words "address" and "pointer" almost
interchangeably.)
I think that, to the extent that the standard does so, it is
defective. Treating the two terms as interchangeable would, if
....
You're using the word "address" in a manner that's inconsistent with
the way the standard uses the word. There are other valid meanings of
the word, but they're no more relevant here than the common meaning of
"byte" as exactly 8 bits.

C99 65.3.2p3:

The unary & operator yields the address of its operand.

This address may or may not be a machine address.
I've already covered that - see above. I've reviewed the standard's uses
of the word "address", and most of them are consistent with my
understanding of address as a concept distinct from the concept of a
pointer (while not clearly supporting that distinction, I have to admit).
Dec 8 '07 #19

P: n/a
pete wrote:
Julienne Walker wrote:
>So please allow me to refine my question: In what cases would the use
of a function name *not* evaluate to a pointer to that function?

There are exactly two cases where
a function name will *not* evaluate to a pointer to that function:
1 As an operand of &
2 As an operand of sizeof
Which of these two cases covers

void func(int i) { ... }
...
(***func)(42);

? "Amongst our weaponry are such diverse elements ..."

--
Eric Sosman
es*****@ieee-dot-org.invalid
Dec 8 '07 #20

P: n/a
On Dec 7, 11:28 pm, Charlton Wilbur <cwil...@chromatico.netwrote:
>>>"J" == Julienne Walker <happyfro...@hotmail.comwrites:
>This is a concept that beginners simply do not need to worry
>about, and making the beginners worry about it when you
>introduce functions is a damn fine way to confuse them.

JI appreciate your concern, but I don't think you're in a
Jposition to make that judgment given nothing more than a quick
Jquestion from me to the experts on clc.

On the contrary; I think, as one of those experts with some teaching
experience, I'm in an excellent position to judge that.
Yet you're only making the judgment based on your assumption of how
I'm going to present the concept.
But carry on; thoroughly confusing beginners is a fine way to make
sure the consulting rates for competent C programmers remain high.
I really do appreciate the warnings, but I'm going to great lengths to
avoid confusing beginners while still teaching correct C.
Charlton

--
Charlton Wilbur
cwil...@chromatico.net
Dec 8 '07 #21

P: n/a
On Dec 8, 2:40 am, Peter Nilsson <ai...@acay.com.auwrote:
Julienne Walker <happyfro...@hotmail.comwrote:
Ignoring implementation details and strictly following
the C99 standard in terms of semantics, is there anything
fundamentally flawed with describing the use of a (non-
inline) function as an address[1]? I keep feeling like
I'm missing something obvious.

Leave 'address' out of it. Just say that all functions are
called through function pointers and that names of functions
decay to function pointers in general expressions, except
in the case of sizeof.
That was the plan, to a certain extent. I think I have more than a
vague idea of how to present this now. Thanks Peter, and everyone else
for your input.
--
PEter
Dec 8 '07 #22

P: n/a
James Kuyper <ja*********@verizon.netwrites:
Keith Thompson wrote:
>James Kuyper <ja*********@verizon.netwrites:
>>Keith Thompson wrote:
ja*********@verizon.net writes:
Keith Thompson wrote:
...
>>>>>function. (The standard uses the words "address" and "pointer" almost
>interchangeably.)
I think that, to the extent that the standard does so, it is
defective. Treating the two terms as interchangeable would, if
...
>You're using the word "address" in a manner that's inconsistent with
the way the standard uses the word. There are other valid meanings of
the word, but they're no more relevant here than the common meaning of
"byte" as exactly 8 bits.

C99 65.3.2p3:

The unary & operator yields the address of its operand.

This address may or may not be a machine address.

I've already covered that - see above. I've reviewed the standard's
uses of the word "address", and most of them are consistent with my
understanding of address as a concept distinct from the concept of a
pointer (while not clearly supporting that distinction, I have to
admit).
I believe the standard uses the word "address" as a synonym of a
"pointer value". I don't believe it ever refers to an object of
pointer type as an "address"; only (non-null) values of pointer type
are called "addresses".

I'm not aware of any statement in the standard that's inconsistent
with the idea that an "address" is the same thing as a pointer value
(even if the pointer value is some composite that incorporates a
machine address plus other information). Can you provide an example?

(I tend to use the unqualified word "pointer" to refer to objects of
pointer type, and the unqualified word "address" to refer to values of
pointer type, but the standard doesn't follow this convention; see for
example, the description of malloc(), which returns "a pointer to the
allocated space".)

--
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"
Dec 8 '07 #23

P: n/a
Eric Sosman wrote:
>
pete wrote:
Julienne Walker wrote:
So please allow me to refine my question:
In what cases would the use
of a function name *not* evaluate to a pointer to that function?
There are exactly two cases where
a function name will *not* evaluate to a pointer to that function:
1 As an operand of &
2 As an operand of sizeof

Which of these two cases covers

void func(int i) { ... }
...
(***func)(42);

?
You've just posted an example of four expressions of function type
each being implicitly converted to a pointer.

--
pete
Dec 8 '07 #24

P: n/a
William Ahern <wi*****@wilbur.25thandClement.comwrites:
[...]
A pointer isn't just an address, either. Pointers can contain other
information beyond, or even in lieu of, the code-space address of the
underlying object.
[...]

Yes, a pointer is just an address. Specifically, an address is simply
a valid non-null value of pointer type. That's the way the standard
uses the term "address"; see the description of the unary "&"
operator. (A C address may or may not be the same as a machine
address, virtual or otherwise.)

--
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"
Dec 9 '07 #25

P: n/a
RoS
In data Sat, 08 Dec 2007 09:29:16 -0800, Keith Thompson scrisse:
>I believe the standard uses the word "address" as a synonym of a
"pointer value". I don't believe it ever refers to an object of
pointer type as an "address"; only (non-null) values of pointer type
are called "addresses".

I'm not aware of any statement in the standard that's inconsistent
with the idea that an "address" is the same thing as a pointer value
(even if the pointer value is some composite that incorporates a
machine address plus other information). Can you provide an example?
char *p=0x1234;
sizeof(p)

so the pointer is not only an address; it is address and other
informations
>(I tend to use the unqualified word "pointer" to refer to objects of
pointer type, and the unqualified word "address" to refer to values of
pointer type, but the standard doesn't follow this convention; see for
example, the description of malloc(), which returns "a pointer to the
allocated space".)
Dec 9 '07 #26

P: n/a
Keith Thompson wrote:
Yes, a pointer is just an address. Specifically, an address is simply
a valid non-null value of pointer type.
I have a problem with the word "valid".

Each of these kinds of pointer values
is more "valid" than the one before:
1 indeterminate
2 null pointer
3 one past
4 object address

The one past pointer is another catagory of pointer values
which I'm not sure if it should be considered an address.

--
pete
Dec 9 '07 #27

P: n/a
Julienne Walker wrote:
So please allow me to refine my question: In what cases would the use
of a function name *not* evaluate to a pointer to that function?
N869
6.3.2 Other operands
6.3.2.1 Lvalues and function designators

[#4] A function designator is an expression
that has function type.
Except when it is the operand of the sizeof operator
or the unary & operator,
a function designator with type
``function returning type''
is converted to an expression that has type
``pointer to function returning type''.

--
pete
Dec 9 '07 #28

P: n/a
On Dec 8, 1:49 pm, Julienne Walker <happyfro...@hotmail.comwrote:
On Dec 7, 11:28 pm, Charlton Wilbur <cwil...@chromatico.netwrote:
>>>>"J" == Julienne Walker <happyfro...@hotmail.comwrites:
>This is a concept that beginners simply do not need to worry
>about, and making the beginners worry about it when you
>introduce functions is a damn fine way to confuse them.
JI appreciate your concern, but I don't think you're in a
Jposition to make that judgment given nothing more than a quick
Jquestion from me to the experts on clc.
On the contrary; I think, as one of those experts with some teaching
experience, I'm in an excellent position to judge that.

Yet you're only making the judgment based on your assumption of how
I'm going to present the concept.
But carry on; thoroughly confusing beginners is a fine way to make
sure the consulting rates for competent C programmers remain high.

I really do appreciate the warnings, but I'm going to great lengths to
avoid confusing beginners while still teaching correct C.
ignoring that I think describing a function as an address to beginners
is a mistake,
I do wonder what the background of your beginners is. You seem to be
introducing quite low level concepts (addresses) quite early.
My memory (from long ago) of being a beginner was that a "function"
was a little program. Fairly rapidly I wanted to know what was
going on underneath, but I was happy to begin with.
--
Nick Keighley
Dec 9 '07 #29

P: n/a
RoS <Ro*@not.existwrites:
In data Sat, 08 Dec 2007 09:29:16 -0800, Keith Thompson scrisse:
>>I believe the standard uses the word "address" as a synonym of a
"pointer value". I don't believe it ever refers to an object of
pointer type as an "address"; only (non-null) values of pointer type
are called "addresses".

I'm not aware of any statement in the standard that's inconsistent
with the idea that an "address" is the same thing as a pointer value
(even if the pointer value is some composite that incorporates a
machine address plus other information). Can you provide an example?

char *p=0x1234;
sizeof(p)

so the pointer is not only an address; it is address and other
informations
Not really. sizeof(p) doesn't refer to the pointer *value*; it yields
the size of a pointer *object*. What I said was that an address is a
pointer value. The current value of ``p'' is a pointer value
(equivalently, I claim, the value of ``p'' is an address). The
*object* ``p'' has more information associated with it than just that
address, just as an object of type int has more information than just,
say, the value 42.

And note that
char *p=0x1234;
is a constraint violation; there's no implicit conversion from int to
char*.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
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"
Dec 10 '07 #30

P: n/a
Keith Thompson wrote:
I believe the standard uses the word "address" as a synonym of a
"pointer value". I don't believe it ever refers to an object of
pointer type as an "address"; only (non-null) values of pointer type
are called "addresses".
That's pretty much the intention. "Address" is not really a useful
term, except for steering the reader's intuition in the right general
direction. The usual IT meaning of "address" is a numerical encoding
used to access the storage location of some information. That's also
what a C pointer value is (apart from a null pointer value). About
the only actual distinction is that a null pointer value might not
correspond to any valid address representation. (But it could..)

The name of a function designates the collection of information used
to implement an invocation of the function. Standard C rules say
that the name of a function is automatically converted into a pointer
(type) to the function in most contexts, and that function calls
(invocations) are always made through pointers to the functions.
So (***foo)(bar) is the same as foo(bar), if foo was declared as a
function designator.
Dec 10 '07 #31

P: n/a
Keith Thompson wrote:
>I believe the standard uses the word "address" as a synonym of a
"pointer value". I don't believe it ever refers to an object of
pointer type as an "address"; only (non-null) values of pointer type
are called "addresses".
Douglas A. Gwyn wrote:
That's pretty much the intention. "Address" is not really a useful
term, except for steering the reader's intuition in the right general
direction. The usual IT meaning of "address" is a numerical encoding
used to access the storage location of some information. That's also
what a C pointer value is (apart from a null pointer value).
I believe the only section of the std that deals with explicit
pointer-to-integer conversions is section 7.18.1.4, which
defines the intptr_t and uintptr_t types, and it uses the
term "pointer".
Dec 11 '07 #32

P: n/a
"Douglas A. Gwyn" <DA****@null.netwrote in message
news:47***************@null.net...
....
The usual IT meaning of "address" is a numerical encoding
used to access the storage location of some information. That's also
what a C pointer value is (apart from a null pointer value).
Actually, no; a C pointer value has a lot of more meaning associated with
it, such as whether it can be dereferenced or not, the range of integers
that can be safely added to it, and so on. It's possible for two C pointers
to look like the same address (and to compare equal) despite the fact that
one of them points to an object (and therefore can be dereferenced but not
decremented) and the other one points past the end of an array (and
therefore can be decremented but not dereferenced). Unfortunately, large
portions of the standard seems to have been written with the narrow
pointer==address model in mind, and are hopelessly unclear on how various
operations propagate the semantic guarantees that a pointer value is
supposed to carry in addition to the address.

Dec 11 '07 #33

P: n/a
Wojtek Lerch wrote:
"Douglas A. Gwyn" <DA****@null.netwrote...
The usual IT meaning of "address" is a numerical encoding
used to access the storage location of some information. That's also
what a C pointer value is (apart from a null pointer value).
Actually, no; a C pointer value has a lot of more meaning associated with
it, such as whether it can be dereferenced or not, the range of integers
that can be safely added to it, and so on.
(Perhaps more importantly, pointers also have types.)

Those are restrictions, not a difference in the fundamental meaning.
It's possible for two C pointers
to look like the same address (and to compare equal) despite the fact that
one of them points to an object (and therefore can be dereferenced but not
decremented) and the other one points past the end of an array (and
therefore can be decremented but not dereferenced).
Again, the model is of storage locations, and there are restrictions
(motivated by a desire for faster execution on some architectures).
... portions of the standard seems to have been written with the narrow
pointer==address model in mind, and are hopelessly unclear on how various
operations propagate the semantic guarantees that a pointer value is
supposed to carry in addition to the address.
There aren't all that many allowed operations for pointers.
Assigning to the same type presumably loses no information.
Subtraction is pretty well spelled out.
Dec 12 '07 #34

P: n/a
"Douglas A. Gwyn" <DA****@null.netwrote in message
news:47***************@null.net...
Wojtek Lerch wrote:
>"Douglas A. Gwyn" <DA****@null.netwrote...
The usual IT meaning of "address" is a numerical encoding
used to access the storage location of some information. That's also
what a C pointer value is (apart from a null pointer value).
Actually, no; a C pointer value has a lot of more meaning associated with
it, such as whether it can be dereferenced or not, the range of integers
that can be safely added to it, and so on.

(Perhaps more importantly, pointers also have types.)
They do, but that's simple. The type can be easily tracked down at compile
time.
Those are restrictions, not a difference in the fundamental meaning.
They draw the line between defined behaviour and undefined behaviour.
That's a pretty fundamental thing in a language standard. When the standard
neglects to tell us where that line is, I'd consider that to be a pretty
fundamental defect.
>It's possible for two C pointers
to look like the same address (and to compare equal) despite the fact
that
one of them points to an object (and therefore can be dereferenced but
not
decremented) and the other one points past the end of an array (and
therefore can be decremented but not dereferenced).

Again, the model is of storage locations, and there are restrictions
(motivated by a desire for faster execution on some architectures).
No, the model is of arrays and their elements. That's how the standard
describes additive operators and equality operators when their operands are
pointers, and a lot of other operations are defined by reference to addition
and equality. The standard seems to assume that for every pointer that
points to an object, the object either is an element of one particular
array, or is not an array element at all. The restrictions are based on
that array. The problem is that for most non-trivial conversions that
produce a pointer value, the standard neglects to mention whether that value
points to an array element or what array that element belongs to; at best,
we're just told where the object it points to is located. When you try to
add an integer to such a pointer, the standard clearly says that the range
of integers that can be added to it is restricted, but fails to explain what
the restriction is.
>... portions of the standard seems to have been written with the narrow
pointer==address model in mind, and are hopelessly unclear on how various
operations propagate the semantic guarantees that a pointer value is
supposed to carry in addition to the address.

There aren't all that many allowed operations for pointers.
There are a lot of differently defined conversions that produce pointers.
Very few of them bother to explain the restriction on the integers that can
be added to the resulting pointer. Nevertheless, the description of the
addition operator makes it clear that there always is a restriction. For
any pointer value, there are some integer values that invoke undefined
behaviour when added to the pointer; but when the pointer is the result of a
conversion, in most cases all the standard tells us about those integer
values is that zero is not one of them.

In some cases it's obvious what the standard really intended to promise us.
For instance, it says that converting a pointer to intptr_t and back
produces a pointer that compares equal to the original. But "everybody
knows" that the standard means to guarantee more than just that -- the
result not only compares equal to the original, but also points to an
element (or past the end) of the same array as the original. In other
words, has the same restrictions on the range of integers that can be added
to it. But the text never actually says that, because that part of the
standard happens to only care about the address ("location") that the
pointer points to, and forgets about the other information (the
"restrictions") that the standard associates with pointer values.
Assigning to the same type presumably loses no information.
The range of integers for which addition has defined behaviour is not the
kind of information that can be preserved or lost by an assignment or
conversion or other operations; it's the kind of information that the
standard should tell us, because without it, the line between defined
behaviour and undefined behaviour is missing. Imagine that the standard
neglected to define the type of certain expressions -- would you also say
that those expressions "lose" the information about the type, or would you
simply say that there's a defect in the standard that needs to be fixed?

Dec 12 '07 #35

P: n/a
Wojtek Lerch wrote:
"Douglas A. Gwyn" <DA****@null.netwrote...
Again, the model is of storage locations, and there are restrictions
(motivated by a desire for faster execution on some architectures).
No, the model is of arrays and their elements. That's how the standard
describes additive operators and equality operators when their operands are
pointers, and a lot of other operations are defined by reference to addition
and equality.
However, the array-of-objects model is overlaid on the byte-array
storage model, even though not much is specified about how pointer
values relate to storage-location indices.
The standard seems to assume that for every pointer that
points to an object, the object either is an element of one particular
array, or is not an array element at all. The restrictions are based on
that array. The problem is that for most non-trivial conversions that
produce a pointer value, the standard neglects to mention whether that value
points to an array element or what array that element belongs to; at best,
we're just told where the object it points to is located. When you try to
add an integer to such a pointer, the standard clearly says that the range
of integers that can be added to it is restricted, but fails to explain what
the restriction is.
Yes, the "where the object is located" is the fundamental semantic
content of the pointer value. The limitations on pointer arithmetic
are a different matter and in fact are virtually never encoded in
the pointer representation.

I'm not sure I understand what your issue is. Every object *can* be
treated as in effect an array of length 1 of objects of that type
(there is wording somewhere in the standard about this), which may
be useful for purposes of understanding validity of pointer arithmetic
for objects *not* declared with array type, but not for much else.
Storage locations correspond to array types only if so declared, or
if such a type is "impressed" upon the storage region as its
"effective type" (we need that for dynamic allocation, but it can
also occur through "punning"). The "type" says how much storage is
involved, how it is aligned, and how the storage content
(representation) is to be interpreted as a "value".

References to separately declared arrays (not "based on" each other)
may be used to create pointer values that are not permitted (in a s.c.
program) to be combined using pointer arithmetic; the only s.c.
relationship between them is (in)equality, which in practice means
that equality comparison may require the C implementation to first
perform some sort of global "address normalization" to ensure correct
results. We didn't require similar normalization for pointer
differencing, because the run-time cost outweighs the extremely
rare utility of that operation for pointers from different segments.

If a pointer value is produced by some chain of conversions that
at some point explicitly involves an array type, then that array
type imposes restrictions on the subsequent allowed pointer
arithmetic. Otherwise (no array bounds explicitly involved),
the only restriction (apart from maximum supported object size) is
whatever is implied by the actual allocation of the referenced
object (declared array length or malloc-specified storage size).
In some cases it's obvious what the standard really intended to promise us.
For instance, it says that converting a pointer to intptr_t and back
produces a pointer that compares equal to the original. But "everybody
knows" that the standard means to guarantee more than just that -- the
result not only compares equal to the original, but also points to an
element (or past the end) of the same array as the original.
I think there is wording elsewhere in the standard that says
that, in connection with pointer equality in general.
Dec 14 '07 #36

P: n/a
"Douglas A. Gwyn" <DA****@null.netwrote in message
news:47***************@null.net...
Wojtek Lerch wrote:
>"Douglas A. Gwyn" <DA****@null.netwrote...
Again, the model is of storage locations, and there are restrictions
(motivated by a desire for faster execution on some architectures).
No, the model is of arrays and their elements. That's how the standard
describes additive operators and equality operators when their operands
are
pointers, and a lot of other operations are defined by reference to
addition
and equality.

However, the array-of-objects model is overlaid on the byte-array
storage model, even though not much is specified about how pointer
values relate to storage-location indices.
It's also overlaid on the union model, and on the
type-punning-by-pointer-conversion model, and might interact with the
effective-type model in an unclear way. That's the problem: one part of the
standard seems to believe that every object is an element of at most one
array, but the rest of the standard introduces pointer conversions, unions,
and other complications, without bothering to explain how they affect the
meaning of "the" array that pointer arithmetic is based on.
> The standard seems to assume that for every pointer that
points to an object, the object either is an element of one particular
array, or is not an array element at all. The restrictions are based on
that array. The problem is that for most non-trivial conversions that
produce a pointer value, the standard neglects to mention whether that
value
points to an array element or what array that element belongs to; at
best,
we're just told where the object it points to is located. When you try
to
add an integer to such a pointer, the standard clearly says that the
range
of integers that can be added to it is restricted, but fails to explain
what
the restriction is.

Yes, the "where the object is located" is the fundamental semantic
content of the pointer value. The limitations on pointer arithmetic
are a different matter and in fact are virtually never encoded in
the pointer representation.
It doesn't matter whether they're encoded or not. Pointer representations
never encode the distinction between a valid pointer and an indeterminate
one either; nevertheless, attempting to use a value that the standard says
is indeterminate produces undefined behaviour. It's important for
programmers to know which values are indeterminate and which ones are not,
and it's the standard's job to tell it to us, because otherwise we wouldn't
know how to avoid undefined behaviour. For exactly the same reason, the
standard needs to tell us the limitations on pointer arithmetic.
Programmers need it to avoid undefined behaviour; implementors need it to
detect opportunities for optimization.
I'm not sure I understand what your issue is. Every object *can* be
treated as in effect an array of length 1 of objects of that type
(there is wording somewhere in the standard about this), which may
be useful for purposes of understanding validity of pointer arithmetic
for objects *not* declared with array type, but not for much else.
Yes, that's pretty much what 6.5.6p7 says, except it talks about "an object
that is not an element of an array", rather than "every object". And, more
importantly, it doesn't clarify whether it's talking about the declared
type, the effective type, the type of the lvalue that was involved in
producing the pointer, or some other type.
Storage locations correspond to array types only if so declared, or
A storage location can correspond to an element of several different arrays
at the same time, if those arrays live inside an object declared as a union.
The standard doesn't seem to clarify anywhere which of those arrays should
be considered "the" array that the object is an element of, for the purpose
of pointer arithmetic.

union {
int v, a[3], b[10], c[2][2]; char d[ 1000 * sizeof(int) ];
} u;

int *p = &u.v;

Does p point to an array element? If it does, then what's the length of the
array? Is p+10 defined? Is p+1000?

What about

int *q = (int*) &u;

Does q point to an element of an array of 3, 10, or 1000 elements, or does
it not point to an array element at all? (My take: according to 6.7.2.1p14,
q points to u.v, because that's the only member of the union that q has the
appropriate type to point to; and since u.v is not an array element, it
should be considered an array of one. Therefore, q+2 is undefined, and a
compiler is free to assume that q[i] and u.a[2] cannot possibly refer to the
same object.)
if such a type is "impressed" upon the storage region as its
"effective type" (we need that for dynamic allocation, but it can
also occur through "punning"). The "type" says how much storage is
involved, how it is aligned, and how the storage content
(representation) is to be interpreted as a "value".
Are you sure that 6.5.6p7 talks about the effective type? I thought the
effective type is about accessing the content of an object, not about
computing pointers. Consider:

struct {
int a[ sizeof(float) ];
int b[ sizeof(float) ];
}
*sptr = malloc( sizeof(*sptr) );

int *iptr = &sptr->b[1] ;
float *fptr = (float*) sptr;

for ( int i = 0; i < 2 * sizeof(int); ++i )
fptr[i] = 0.0; // Impress "float" as the effective type

At this point, does iptr still point to the second element of an array of
ints, as far as 6.5.6p7 is concerned? Is iptr-1 still defined?

And what about iptr-2?

....
If a pointer value is produced by some chain of conversions that
at some point explicitly involves an array type, then that array
type imposes restrictions on the subsequent allowed pointer
arithmetic.
I don't think you can have it both ways. Either it's based on the effective
type of what the pointer points to, or on the history of conversions and
arithmetic that produced the pointer.
Otherwise (no array bounds explicitly involved),
the only restriction (apart from maximum supported object size) is
whatever is implied by the actual allocation of the referenced
object (declared array length or malloc-specified storage size).
That's the opposite of what the standard says. According to 6.5.6p7, if no
array is involved, then the pointer should be considered to point to the
element of a one-element array; therefore you can't decrement it, and you
can only increment it once.
>In some cases it's obvious what the standard really intended to promise
us.
For instance, it says that converting a pointer to intptr_t and back
produces a pointer that compares equal to the original. But "everybody
knows" that the standard means to guarantee more than just that -- the
result not only compares equal to the original, but also points to an
element (or past the end) of the same array as the original.

I think there is wording elsewhere in the standard that says
that, in connection with pointer equality in general.
I don't, and believe me, I looked. As you must know, pointer equality
allows two pointers based on different arrays to compare equal. It
explicitly talks about the case of comparing a pointer to the first element
of an array with a pointer past the end of a different array. It also
implicitly covers the case where two pointers point to the same object but
consider that object to be an element of two different arrays (such as
&u.a[1] and &u.b[1] from my example).
Dec 14 '07 #37

This discussion thread is closed

Replies have been disabled for this discussion.