whats wrong with this pointer operation?

  • Thread starter =?ISO-8859-1?Q?Martin_J=F8rgensen?=
  • Start date
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Hi,

"C primer plus" p.382:

Suppose we have this declaration:

int (*pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2;


Then this is okay:
pa = ar1; // both pointer-to-int[3]


But these are not:
pa = ar2; // why not?
p2 = ar2; // why not?



ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
pointer-to-int-array).

And pa must be a pointer to int[3]-array... So in my opinion pa = ar2
should work but the book says "not valid"...? I also think that p2 = ar2
should work, but that seems wrong according to the book?



Best regards / Med venlig hilsen
Martin Jørgensen
 
P

pinkfog

Martin said:
Hi,

"C primer plus" p.382:

Suppose we have this declaration:

int (*pa)[3];
you can give a example to understand it.This expression means:
an 2_D array: int* pa_0 ,int * pa_1 ,int* pa_2 ,that is to say: in the
2-D array form ,there are integers of size_t rows and 3 colums .
int ar1[2][3];
int ar2[3][2];
int **p2;
So ar1: 2 rows and 3 colums
ar2: 3 rows and 2 colums
p2: unknown size
Then this is okay:
pa = ar1; // both pointer-to-int[3]

Right. The assignment makes pa a 2*3 2_D array.
But these are not:
pa = ar2; // why not?
p2 = ar2; // why not?

Wrong. ar2 and pa are not of the same size.
ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
pointer-to-int-array).

And pa must be a pointer to int[3]-array... So in my opinion pa = ar2
should work but the book says "not valid"...? I also think that p2 = ar2
should work, but that seems wrong according to the book?
Hope this can help a little.
----------------------pinkfog-----------------------
 
K

Keith Thompson

Martin Jørgensen said:
"C primer plus" p.382:

Suppose we have this declaration:

int (*pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2;


Then this is okay:
pa = ar1; // both pointer-to-int[3]

Right. ar1 is an array[2] of array[3] of int; it decays to a pointer
to array[3] of int. Since pa is explicitly pointer to array[3] of
int, the types match.
But these are not:
pa = ar2; // why not?
p2 = ar2; // why not?

ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
pointer-to-int-array).

No. Arrays are not pointers. Pointers are not arrays. There is no
pointer-to-pointer here.

The declaration
int ar2[3][2];
declares ar2 as an array[3] of array[2] of int. The memory allocated
for it is enough to hold 3*2 int objects (6 * sizeof(int)). The name
ar2, in most contexts, decays to a pointer to array[2] of int; this
is a pointer value, not a pointer object.

This declaration does *not* create a pointer-to-pointer. No space is
allocated for any pointer object. A pointer-to-pointer and a
pointer-to-array are two different things; neither may be converted to
the other. A pointer *value* may be created when the name ar2 is used
in an expression, but only a pointer to array[2] of int, not any kind
of pointer-to-pointer.

In
pa = ar2;
pa is of type pointer to array[3] of int, and ar2 is of type array[3]
of array[2] of int, which decays to pointer to array[2] of int.
Though both sides are pointers to array of int, the types don't match
because they're pointers to arrays of different lengths.

In
p2 = ar2;
p2 is a pointer to pointer to int, and as we've seen, ar2 is not, and
does not decay into, a pointer to pointer. Again, the types are
incompatible.

If you haven't already, read section 6 of the comp.lang.c FAQ,
"Pointers and Arrays".
 
?

=?ISO-8859-1?Q?Martin_J=F8rgensen?=

Keith said:
Martin Jørgensen said:
"C primer plus" p.382:

Suppose we have this declaration:

int (*pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2;


Then this is okay:
pa = ar1; // both pointer-to-int[3]


Right. ar1 is an array[2] of array[3] of int; it decays to a pointer
to array[3] of int. Since pa is explicitly pointer to array[3] of
int, the types match.

Uh, yes... I forgot to look at the column-size...
But these are not:
pa = ar2; // why not?
p2 = ar2; // why not?

ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
pointer-to-int-array).


No. Arrays are not pointers. Pointers are not arrays. There is no
pointer-to-pointer here.
Ofcourse...

The declaration
int ar2[3][2];
declares ar2 as an array[3] of array[2] of int. The memory allocated
for it is enough to hold 3*2 int objects (6 * sizeof(int)). The name
ar2, in most contexts, decays to a pointer to array[2] of int; this
is a pointer value, not a pointer object.

Thanks a lot... I just have to make sure: What exactly do you mean by:

1) Pointer value

2) Pointer object

What's the difference? C isn't "object-oriented" as in C++ so I just
want to make sure I understand the difference...
This declaration does *not* create a pointer-to-pointer. No space is
allocated for any pointer object. A pointer-to-pointer and a
pointer-to-array are two different things; neither may be converted to
the other. A pointer *value* may be created when the name ar2 is used
in an expression, but only a pointer to array[2] of int, not any kind
of pointer-to-pointer.

Thanks... Makes sense.
In
pa = ar2;
pa is of type pointer to array[3] of int, and ar2 is of type array[3]
of array[2] of int, which decays to pointer to array[2] of int.

Sounds to me like: I've read something about that there is a similarity
between declaring array[3][2] and declaring array[][2] in a function
header...

Is that what you mean by "decaying into"?
Though both sides are pointers to array of int, the types don't match
because they're pointers to arrays of different lengths.

It's only the column-size that must match, isn't it?
In
p2 = ar2;
p2 is a pointer to pointer to int, and as we've seen, ar2 is not, and
does not decay into, a pointer to pointer. Again, the types are
incompatible.

If you haven't already, read section 6 of the comp.lang.c FAQ,
"Pointers and Arrays".

I think I've read it a couple of times... But I just forgot something
which I now remember...

It isn't that hard for me to understand... That's why I only got a few
comments here - I agree with what you wrote, after reading it...


Best regards / Med venlig hilsen
Martin Jørgensen
 
M

Mark McIntyre

Thanks a lot... I just have to make sure: What exactly do you mean by:

1) Pointer value

2) Pointer object

int x=3;

x is an int object

3 is its int value

Same thing with pointers.
Sounds to me like: I've read something about that there is a similarity
between declaring array[3][2] and declaring array[][2] in a function
header...

Is that what you mean by "decaying into"?

No, but its related.
When an array is passed to a function, it is "decayed" into a pointer
to its first element. Inside the function, there is no array, only the
pointer.
The example you give is a consequence of this. Since the array decays
into a pointer, there is no use declaring its (first) dimension.

It's only the column-size that must match, isn't it?

Please don't think of it as columns and rows - its not like that. What
will you do when you get to 3, 4 or 5 dimensions?

And AFAIK the types will only match if all dimensions match.

Mark McIntyre
 
D

Default User

Martin said:
Keith said:
Martin Jørgensen said:
"C primer plus" p.382:

Suppose we have this declaration:

int (*pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2;


Then this is okay:
pa = ar1; // both pointer-to-int[3]


Right. ar1 is an array[2] of array[3] of int; it decays to a
pointer to array[3] of int. Since pa is explicitly pointer to
array[3] of int, the types match.

Uh, yes... I forgot to look at the column-size...
But these are not:
pa = ar2; // why not?
p2 = ar2; // why not?

ar1 and ar2 must be the same type: pointer-to-pointer-to-int (or
pointer-to-int-array).


No. Arrays are not pointers. Pointers are not arrays. There is no
pointer-to-pointer here.
Ofcourse...

The declaration
int ar2[3][2];
declares ar2 as an array[3] of array[2] of int. The memory
allocated for it is enough to hold 3*2 int objects (6 *
sizeof(int)). The name ar2, in most contexts, decays to a pointer
to array[2] of int; this is a pointer value, not a pointer object.

Thanks a lot... I just have to make sure: What exactly do you mean by:

1) Pointer value

2) Pointer object

What's the difference? C isn't "object-oriented" as in C++ so I just
want to make sure I understand the difference...

From the draft standard:

3.15
[#1] object
region of data storage in the execution environment, the
contents of which can represent values

[#2] NOTE When referenced, an object may be interpreted as
having a particular type; see 6.3.2.1.

So pointer objects can hold pointer values.

Sounds to me like: I've read something about that there is a
similarity between declaring array[3][2] and declaring array[][2] in
a function header...

The leftmost dimension isn't necessary in function declarations,
because you can't pass arrays, only pointers to the first element.
That's why you can have:

void func(int *p);
void func(int p[]);

They both mean the same thing. In the case of a mult-dimension array,
the first element is another array.
Is that what you mean by "decaying into"?

In most contexts, the name of an array is converted to a pointer to the
first element. Exceptions include with the array name is used with the
sizeof operator or the address-of (&) operator.
It's only the column-size that must match, isn't it?

Everything but the left-most dimension. So if it was a three-D array,
the two right dimensions would have to match.



Brian
 
K

Keith Thompson

Martin Jørgensen said:
Keith said:
The declaration
int ar2[3][2];
declares ar2 as an array[3] of array[2] of int. The memory allocated
for it is enough to hold 3*2 int objects (6 * sizeof(int)). The name
ar2, in most contexts, decays to a pointer to array[2] of int; this
is a pointer value, not a pointer object.

Thanks a lot... I just have to make sure: What exactly do you mean by:

1) Pointer value

2) Pointer object

What's the difference? C isn't "object-oriented" as in C++ so I just
want to make sure I understand the difference...

Right, the term "object" in C has nothing to do with "object-oriented"
anything. The standard's definition of "object" is a "region of data
storage in the execution environment, the contents of which can
represent values" (C99 3.14).

Loosely speaking, it's nearly the same thing as a variable. An object
can also be a component of another object, or the chunk of memory
allocated by malloc(). (The standard doesn't define the term
"variable".)

A value is the result of evaluating an expression. It isn't
necessarily stored anywhere; it's a transient thing that exists only
while the expression is being evaluated, unless it's stored in an
object.

An object name is an expression; the value of the expression is the
value that was stored in the object.

A pointer object is an object of pointer type; the value of a pointer
object is a pointer value, also known as an address.

(There's some controversy in this area. Some people feel strongly
that the unadorned word "pointer" should refer only to a pointer
object, never to a value -- but the standard, like it or not, talks
about functions returning pointers. I usually try to avoid the issue
by referring explicitly to pointer objects and pointer values.)
[...]
In
pa = ar2;
pa is of type pointer to array[3] of int, and ar2 is of type array[3]
of array[2] of int, which decays to pointer to array[2] of int.

Sounds to me like: I've read something about that there is a
similarity between declaring array[3][2] and declaring array[][2] in a
function header...

Is that what you mean by "decaying into"?

No, that's something different (but related, I suppose).

A function can't have a parameter of array type. You can declare
something that *looks* like an array parameter:
void foo(char param[]);
but, because of a special-case rule, that's exactly the same as:
void foo(char *param);
The same is true if you specify the length of the aray:
void foo(char param[42]);
The length is just quietly ignored.

The intent of the rule is to allow you to indicate that the argument
is expected to be an array (which will decay to a pointer), but in my
opinion this rule causes more problems than it solves.

Your example:
void bar(int array[3][2]);
vs.
void bar(int array[][2]);
is just a special case of this, where the array's element type happens
to be another array type.

But when I used the phrase "decaying into", I was referring to the
implicit conversion of array expressions to pointer type.

In most contexts, an expression of array type (such as the name of a
declared array object) is implicitly converted to a pointer to the
array's first element. The exceptions are: (1) the argument to the
"sizeof" operator, (2) the argument to the "&" operator, and (3) a
string literal used in an initialize an array.
It's only the column-size that must match, isn't it?

In this case, yes (of course the element type must match as well).
But a better way to think about it is that the types must match, after
any implicit conversions have been applied. A two-dimensional array
is just an array of arrays. There are no special rules for
multi-dimensional arrays; their behavior is determined entirely by the
rules for one-dimensional arrays, including implicit conversions to
pointers.
 
K

Keith Thompson

Mark McIntyre said:
On Thu, 20 Apr 2006 16:27:17 +0200, in comp.lang.c , Martin Jørgensen
Sounds to me like: I've read something about that there is a similarity
between declaring array[3][2] and declaring array[][2] in a function
header...

Is that what you mean by "decaying into"?

No, but its related.
When an array is passed to a function, it is "decayed" into a pointer
to its first element. Inside the function, there is no array, only the
pointer.
The example you give is a consequence of this. Since the array decays
into a pointer, there is no use declaring its (first) dimension.

Right. And this is just one case of a more general rule, having
nothing to do with function calls. An expression of array type is (in
most contexts) implicitly converted to a pointer to its first element.
This applies whether it's a function argument, the right hand side of
an assignment, or the operand of a "+" operator (with the exceptions
that have already been mentioned several times in this thread).

It even applies to the array indexing operator. For example:

int arr[10];
int x = arr[5];

The indexing operator takes two operands, a pointer and an integer.
If one of its operands is the name of an array, that operand is
implicitly converted to a pointer. An indexing operator "x[y]" is by
definition equivalent to "*(x+y)". It's most commonly used on arrays,
of course, but that's just a special case; it's defined to work on
pointers.
 

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

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top