Converting to/from pointer

J

James Kanze

"An array always evalues ("decays") to a constant pointer to its
first element, except as the operand of sizeof or of the unary &.
For example, given:
int arr[100];
int * const ptr = &arr[0];
Every expression containing arr will have the same identical value
that it would have if arr were replaced with ptr, unless arr is
used as the operand of & or sizeof."
Too complicated for students? If so, you'd better teach those
students some other language.
You forgot one case: a string literal used to initialize an array
doesn't decay to a pointer.

Sort of. He did say "evalues". Maybe (probably?) he meant by
that "when used in an expression". After all, the first use of
arr in his example doesn't decay to a constant pointer; "int
arr[100]" is a very different beast than "int *const arr;". And
initialization of an array of char with a string literal is
arguably a special case, where the initializer is not an
expression (although that's not quite the way I'd explain it).

Anyway, my point is that you can't talk about arrays and
pointers in expressions without first talking about declaring
them, so you have to start with their being different things;
you can't avoid it.
 
M

Malcolm McLean

Army1987 said:
"An array always evalues ("decays") to a constant pointer to its
first element, except as the operand of sizeof or of the unary &.
For example, given:
int arr[100];
int * const ptr = &arr[0];
Every expression containing arr will have the same identical value
that it would have if arr were replaced with ptr, unless arr is
used as the operand of & or sizeof."

Too complicated for students? If so, you'd better teach those
students some other language.
The students are just learning what the terms "array" and "pointer" mean.
Then you are throwing "operand", sizeof, and "unary &" at them.
It is a classic case of defining something rather than explaining it.

The better students will of course learn despite poor teaching. The problem
is that the marginal ones may decide that C is not for them, when in fact it
could have been a useful skill not too hard to acquire.
 
J

Johan Bengtsson

Army1987 said:
And usually the teacher answers "I did it on purpose, I wanted to
check wheter you were paying enough attention"... :)
I have used that answer myself ocassionaly (as a teacher obviously) at
in some cases it was true, in some cases it was not true and in yet some
cases (actually more of those) I have admitted that I did wrong.

That answer is usually not satisfactory however when a test is judged
wrong and I actually had to physically prove my solution right before it
was accepted. - That was one of the cases when it happened to me at
school that I still remember clearly. (A physics test concerning how a
NPN transistor works)
 
F

Flash Gordon

Malcolm McLean wrote, On 09/06/07 08:54:
Army1987 said:
"An array always evalues ("decays") to a constant pointer to its
first element, except as the operand of sizeof or of the unary &.
For example, given:
int arr[100];
int * const ptr = &arr[0];
Every expression containing arr will have the same identical value
that it would have if arr were replaced with ptr, unless arr is
used as the operand of & or sizeof."

Too complicated for students? If so, you'd better teach those
students some other language.
The students are just learning what the terms "array" and "pointer"
mean. Then you are throwing "operand", sizeof, and "unary &" at them.

If you have not explained what an operand is before getting on to arrays
and pointers then you are doing something VERY wrong. sizeof can easily
be explained prior to doing arrays and pointers, it is not difficult.
Then you just have the unary & to explain when starting on pointers
which is not exactly difficult.
It is a classic case of defining something rather than explaining it.

The better students will of course learn despite poor teaching. The
problem is that the marginal ones may decide that C is not for them,
when in fact it could have been a useful skill not too hard to acquire.

I'm not sure whether you are in favour of claiming that arrays and
pointers are very similar or not, only that you don't favour explaining
arrays decaying to pointers at the start of explaining arrays and pointer.

Personally I would explain arrays and pointers completely separately and
only go on to arrays decaying to pointers once arrays and pointers are
understood.
 
C

Clark Cox

"An array always evalues ("decays") to a constant pointer to its
first element, except as the operand of sizeof or of the unary &.
For example, given:
int arr[100];
int * const ptr = &arr[0];
Every expression containing arr will have the same identical value
that it would have if arr were replaced with ptr, unless arr is
used as the operand of & or sizeof."
Too complicated for students? If so, you'd better teach those
students some other language.
You forgot one case: a string literal used to initialize an array
doesn't decay to a pointer.

Sort of. He did say "evalues". Maybe (probably?) he meant by
that "when used in an expression".

The right side of the equals sign in an initialization *is* an
expression; and it *is* evaluated.
After all, the first use of
arr in his example doesn't decay to a constant pointer; "int
arr[100]" is a very different beast than "int *const arr;". And
initialization of an array of char with a string literal is
arguably a special case, where the initializer is not an
expression (although that's not quite the way I'd explain it).

How is it not an expression? And if it isn't an expression, then what is it?

C:
From 6.5.1 4:
"A string literal is a primary expression."

C++
From [expr.prim] 2:
"A literal is a primary expression. Its type depends on its form
(2.13). A string literal is an lvalue; all other
literals are rvalues."

Seems pretty clear to me in both languages.
 
A

Army1987

"James Kanze" <[email protected]> ha scritto nel messaggio
"An array always evalues ("decays") to a constant pointer to its
first element, except as the operand of sizeof or of the unary &.
For example, given:
int arr[100];
int * const ptr = &arr[0];
Every expression containing arr will have the same identical value
that it would have if arr were replaced with ptr, unless arr is
used as the operand of & or sizeof."
Too complicated for students? If so, you'd better teach those
students some other language.
You forgot one case: a string literal used to initialize an array
doesn't decay to a pointer.

Sort of. He did say "evalues". Maybe (probably?) he meant by
that "when used in an expression".

Yeah. I meant that. Obviously an array doesn't decay to anything
when it is not used at all, but I forgot about the way an array can
be "used" other than within an expression (i.e. in a declaration).
And the syntax says
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
expression:
assignment-expression
expression , assignment-expression
so a string literal used to initialize an array *is* an expression,
so it *is* an exception to "an array within an expression decays to
a pointer to its beginning" which I did forget to mention.
 
A

Army1987

Malcolm McLean said:
Army1987 said:
"An array always evalues ("decays") to a constant pointer to its
first element, except as the operand of sizeof or of the unary &.
For example, given:
int arr[100];
int * const ptr = &arr[0];
Every expression containing arr will have the same identical value
that it would have if arr were replaced with ptr, unless arr is
used as the operand of & or sizeof."

Too complicated for students? If so, you'd better teach those
students some other language.
The students are just learning what the terms "array" and "pointer" mean.
Then you are throwing "operand", sizeof, and "unary &" at them.
It is a classic case of defining something rather than explaining it.

The better students will of course learn despite poor teaching. The
problem is that the marginal ones may decide that C is not for them, when
in fact it could have been a useful skill not too hard to acquire.

So: first I'd teach them what an array is and how to use it, telling that
they can't assign to an array or compare two arrays with ==. Then (maybe
even weeks later) I'd explain them what a pointer is, including what & does.
Then I would tell them about the
fact that arrays decay into pointers as above.
 
P

pete

Army1987 wrote:
So: first I'd teach them what an array is and how to use it,
telling that
they can't assign to an array or compare two arrays with ==.
Then (maybe even weeks later)
I'd explain them what a pointer is, including what & does.
Then I would tell them about the
fact that arrays decay into pointers as above.

I don't know much about pedagogy,
but I think that before that, I would teach that
sizeof((char)0 + (char)0 + (char)0) equals sizeof(int).
 
M

Malcolm McLean

Flash Gordon said:
Malcolm McLean wrote, On 09/06/07 08:54:
Army1987 said:
"An array always evalues ("decays") to a constant pointer to its
first element, except as the operand of sizeof or of the unary &.
For example, given:
int arr[100];
int * const ptr = &arr[0];
Every expression containing arr will have the same identical value
that it would have if arr were replaced with ptr, unless arr is
used as the operand of & or sizeof."

Too complicated for students? If so, you'd better teach those
students some other language.
The students are just learning what the terms "array" and "pointer" mean.
Then you are throwing "operand", sizeof, and "unary &" at them.

If you have not explained what an operand is before getting on to arrays
and pointers then you are doing something VERY wrong. sizeof can easily be
explained prior to doing arrays and pointers, it is not difficult. Then
you just have the unary & to explain when starting on pointers which is
not exactly difficult.
It is a classic case of defining something rather than explaining it.

The better students will of course learn despite poor teaching. The
problem is that the marginal ones may decide that C is not for them, when
in fact it could have been a useful skill not too hard to acquire.

I'm not sure whether you are in favour of claiming that arrays and
pointers are very similar or not, only that you don't favour explaining
arrays decaying to pointers at the start of explaining arrays and pointer.

Personally I would explain arrays and pointers completely separately and
only go on to arrays decaying to pointers once arrays and pointers are
understood.
One problem is that when we take this example

int x;
int *ptr = &x;

it is quite hard to explain the advantage of the operation.

Pointers don't actually make much sense until you've got a reasonable amount
of code. Then the increment rule is so fundamental that really you must
introduce pointers to arrays very quickly.

So it should be arrays, then function calls, and then pointers and how to
pass arrays to functions. sizeof() doesn't make much sense outside of a
pointer context. Introduce when you come to malloc(), which has to be after
pointers to arrays are mastered.
 
P

peter koch

I believe you are wrong here, in that the number of terms in the
expression doesn't matter, provided there is at least one term.

I believe that the poster wanted to tell about the difference between
C and C++ wrt. sizeof('a').

/Peter
 
H

Harald van =?UTF-8?B?RMSzaw==?=

CBFalconer said:
I believe you are wrong here, in that the number of terms in the
expression doesn't matter, provided there is at least one term.

If there is exactly one term, the usual arithmetic conversions aren't
necessarily performed. If there are multiple terms, they are.

sizeof((char)0) is always 1, because if there is exactly one term, such as
(char)0 here, it does not get promoted. sizeof((char)0 + (char)0) is always
sizeof(int), because the integer promotions are applied to both terms.
 
K

Keith Thompson

Clark Cox said:
The right side of the equals sign in an initialization *is* an
expression; and it *is* evaluated.

It's not an expression if it's enclosed in curly braces; for example:

struct foo obj = { 10, 20 };

That doesn't contradict your main point, though.
 
K

Keith Thompson

Malcolm McLean said:
One problem is that when we take this example

int x;
int *ptr = &x;

it is quite hard to explain the advantage of the operation.

I'm not convinced that the student has to understand why each concept
is useful at the time that it's presented. The "hello, world" program
isn't particularly useful by itself; I think most students can
understand that it's leading to something else.
Pointers don't actually make much sense until you've got a reasonable
amount of code. Then the increment rule is so fundamental that really
you must introduce pointers to arrays very quickly.

I assume you're referring to the fact that an array can be accessed
via a pointer to its first element. Actual pointers to arrays are
rarely useful.
So it should be arrays, then function calls, and then pointers and how
to pass arrays to functions. sizeof() doesn't make much sense outside
of a pointer context.

sizeof makes perfect sense; it yields the size in bytes of its
argument. The *usefulness* of sizeof isn't quite as obvious.
Introduce when you come to malloc(), which has
to be after pointers to arrays are mastered.

Pointers to structures can be used to build linked lists and other
dynamic data structures. (I'm not sure that such things should be
introduced before arrays, though.)
 
K

Keith Thompson

peter koch said:
I believe that the poster wanted to tell about the difference between
C and C++ wrt. sizeof('a').

I believe both of you missed the point.

pete's statement that

sizeof((char)0 + (char)0 + (char)0) equals sizeof(int)

is correct in both C and C++. (char)0 is of type char, but it's
promoted to int when used in an expression. (It could be promoted to
unsigned int in some exotic implementations, but sizeof(unsigned int)
== sizeof(int), so that wouldn't affect the truth of the statement.)

It's true that C and C++ treat character constants differently, but
there are no character constants in pete's code.

What *I'm* missing is why pete thinks this particular odd fact should
be taught before teaching arrays and pointers.
 
P

pete

((char)0) is an expression of type char.
((char)0 + (char)0) is an expression of type int or type unsigned.
I believe both of you missed the point.

pete's statement that

sizeof((char)0 + (char)0 + (char)0) equals sizeof(int)

is correct in both C and C++. (char)0 is of type char, but it's
promoted to int when used in an expression.

"used in an expression" is insufficient to cause the conversion
of low ranking integer type expressions.
Array types and function types,
are the only types that the standard describes as
being always converted except in certain circumstances.

If the right operand of a shift operator is of type char,
it won't be converted.
(It could be promoted to
unsigned int in some exotic implementations, but sizeof(unsigned int)
== sizeof(int), so that wouldn't affect the truth of the statement.)

It's true that C and C++ treat character constants differently, but
there are no character constants in pete's code.

What *I'm* missing is why pete thinks this particular odd fact should
be taught before teaching arrays and pointers.

The particular odd fact is relevant to
the topic of implicit conversions, which is the juicy part
of the relationship between arrays and pointers.

This statement by Army1987:made me wonder if the topics of
expressions and types and implicit conversions,
might be best presented before the topic of "array decay".
 
P

pete

pete said:
"used in an expression" is insufficient to cause the conversion
of low ranking integer type expressions.
Array types and function types,
are the only types that the standard describes as
being always converted except in certain circumstances.

If the right operand of a shift operator is of type char,
it won't be converted.

Oops. That's wrong.
But the point that I was trying to get at is that
the integer promotions are described as "only"
taking place under certain circumstances
and that
"used in an expression" is insufficient to cause the conversion
of low ranking integer type expressions.


N869
6.3.1.3 Signed and unsigned integers

42)The integer promotions are applied only: as part of the
usual arithmetic conversions, to certain argument
expressions, to the operands of the unary +, -, and ~
operators, and to both operands of the shift operators,
as specified by their respective subclauses.
 
F

Flash Gordon

Keith Thompson wrote, On 09/06/07 20:39:
I'm not convinced that the student has to understand why each concept
is useful at the time that it's presented. The "hello, world" program
isn't particularly useful by itself; I think most students can
understand that it's leading to something else.

However, using pointers as parameters to functions is very useful, so if
you want to introduce pointers (but not all they can do) before arrays
it is easily possible. I would not, but it can be done.

You can make sensible use of them in 100 lines or less.
I assume you're referring to the fact that an array can be accessed
via a pointer to its first element. Actual pointers to arrays are
rarely useful.
Agreed.


sizeof makes perfect sense; it yields the size in bytes of its
argument. The *usefulness* of sizeof isn't quite as obvious.
Agreed.


Pointers to structures can be used to build linked lists and other
dynamic data structures. (I'm not sure that such things should be
introduced before arrays, though.)

I strongly agree with this. An array is a far simpler data structure and
so should be introduced first. They can be taught without ever having to
mention the relationship to pointers, although for some usage you have
to start getting close.
 
K

Keith Thompson

CBFalconer said:
I didn't. Read what I wrote again.

Ok.

....

The second part of your statement is correct (the number of terms in
the expression doesn't matter, provided there is at least one term),
but I don't see how it implies that pete was wrong.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top