470,870 Members | 1,276 Online

# Pointer conversions

Are the following guaranteed to work always as *C90* code?

1.

#include <stdio.h>
void some_func(int *p, const size_t SIZE)
{
size_t i;

for(i=0; i<SIZE; ++i)
printf("%d ", p[i]);
}
int main(void)
{
int array[10][5]= {0};

some_func(array[0], sizeof(array)/sizeof(**array));

puts("");

return 0;
}

The above prints 50 zeros. I think it is guaranteed to work, since all
arrays are sequences of their elements.

2.

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t i, j;

int array[50]= {0};

int (*p)[5]= (int (*)[5])(&array[0]);

for (i= 0; i< 10; ++i)
for(j=0; j<5; ++j)
printf("%d ", p[i][j]);

puts("");

return 0;
}
Here p behaves as a 2-dimensional matrix, that is a 10x5 matrix. I think
it is guaranteed to work for the same reason as the first one, that is
we can treat an array (sequence) of integers as various types of integer
arrays.
Jan 5 '08 #1
26 1671
Ioannis Vranos wrote:
>
Are the following guaranteed to work always as *C90* code?

1.

#include <stdio.h>

void some_func(int *p, const size_t SIZE)
{
size_t i;

for(i=0; i<SIZE; ++i)
printf("%d ", p[i]);
}

int main(void)
{
int array[10][5]= {0};

some_func(array[0], sizeof(array)/sizeof(**array));

puts("");

return 0;
}

The above prints 50 zeros. I think it is guaranteed to work, since all
arrays are sequences of their elements.
It is not guaranteed to work.
The problem is that there is no array of int
with more than 5 members declared anywhere.

Pointers to char are allowed to step through the bytes
of any object, but that's by a special rule.

I can't conceive of any mechanism by which your code could fail,
but the guarantee of which you speak, is not there.

is over running the boundaries of an array of 5 int.

--
pete
Jan 6 '08 #2
Ioannis Vranos wrote:
Are the following guaranteed to work always as *C90* code?
[ Treating an int array[10][5] as it were int array[1][50] ]
That's one of those things for which the standard defines no behavior,
without any reason not to do define one. I'd be very surprised if it
failed, but that would not make an implementation non-conforming. Unless
there is some implementation on which that fails, I'd not object to it
being allowed.
(Another such thing is the struct hack, or printing a nonnegative signed
int with %x. They can fail, but I can't see any way in which they could,
other than the implementation being *intentionally* hostile.)

--
Army1987 (Replace "NOSPAM" with "email")
Jan 6 '08 #3
On Sun, 06 Jan 2008 13:53:56 +0000, Army1987 wrote:
Ioannis Vranos wrote:
>Are the following guaranteed to work always as *C90* code?
[ Treating an int array[10][5] as it were int array[1][50] ] That's one
of those things for which the standard defines no behavior, without any
reason not to do define one. I'd be very surprised if it failed, but
that would not make an implementation non-conforming. Unless there is
some implementation on which that fails, I'd not object to it being
allowed.
As I recall, it does fail on some implementations, because the optimiser
doesn't realise it's possible for p1[10][3] and p2[5][8] to overlap (and
in fact it isn't possible in standard C), so code such as

p1[10][3] = 5;
p2[5][8] = 3;
return p1[10][3];

would return 5 without re-reading p1[10][3]. However, I cannot come up
with a concrete example showing the behaviour right now. It was with one
version of GCC, but the one I'm using now appears to handle array
accesses differently.
Jan 6 '08 #4

"Army1987" <ar******@NOSPAM.itwrote in message
news:fl**********@tdi.cu.mi.it...
Ioannis Vranos wrote:
>Are the following guaranteed to work always as *C90* code?
[ Treating an int array[10][5] as it were int array[1][50] ]
That's one of those things for which the standard defines no behavior,
without any reason not to do define one. I'd be very surprised if it
failed, but that would not make an implementation non-conforming. Unless
there is some implementation on which that fails, I'd not object to it
being allowed.
(Another such thing is the struct hack, or printing a nonnegative signed
int with %x. They can fail, but I can't see any way in which they could,
other than the implementation being *intentionally* hostile.)
I have an example:
consider the C implementation is built on top of a VM framework of some
sort;
this VM does not allow multidimensional arrays as such, but treats the case
of multidimensional arrays as a nested set of 1D arrays.

all works well, as long as we use the array as specified.
going outside this, the implementation may well crash, issue bounds-check
exceptions, ...

so, in general, I would personally probably advise against relying on this
kind of behavior (instead, when needed, faking multidimensional arrays using
larger 1D arrays, so that the multidimensional case need not be compromised
as such).

in my case, for my compiler I had actually been fairly tempted originally to
implement multidimensional arrays like the previous, but decided against it
(my main reason though, was more that it would have made gcc integration
more problematic).
meanwhile, I am considering an idea for adding lexical closures to my
compiler (inner functions + a __lambda keyword).

this would be pulled off, in this case, by allocating both the function
stub, and captured bindings, in an area of "non-reclaimable" memory. as
such, it would only be possible to make a finite (though possibly still
reasonably large) number of them during the operation of the program.

otherwise, they would be made to look and behave just like ordinary function
pointers.

--
Army1987 (Replace "NOSPAM" with "email")

Jan 6 '08 #5
cr88192 <cr*****@hotmail.comwrote:
"Army1987" <ar******@NOSPAM.itwrote in message
news:fl**********@tdi.cu.mi.it...
Ioannis Vranos wrote:
Are the following guaranteed to work always as *C90* code?
[ Treating an int array[10][5] as it were int array[1][50] ]
[ ... ] Unless
there is some implementation on which that fails, I'd not object to it
being allowed.
I have an example:
consider the C implementation is built on top of a VM framework of some
sort;
this VM does not allow multidimensional arrays as such, but treats the case
of multidimensional arrays as a nested set of 1D arrays.
I don't see how that affects C. The OP's int array[10][5] has to
be laid out in memory the same way as an int [50]. If the VM or hardware
has some weird facility, the C implementation is not obligated to use it.
all works well, as long as we use the array as specified.
going outside this, the implementation may well crash, issue bounds-check
exceptions, ...
It looks like a conforming implementation could stuff bounds
information into fat pointers and trap at runtime. That could be
tolerable to me as an extension, but if the behavior can't be switched
off the an implementation would be disqualified as far as I am
concerned.

so, in general, I would personally probably advise against relying on this
kind of behavior (instead, when needed, faking multidimensional arrays using
larger 1D arrays, so that the multidimensional case need not be compromised
as such).
Yeah, if you like ugly code. These days I deal with arrays of 3n floats;
in some parts of the code it is more convenient to view them as nx3 arrays,
in others it is more convenient to treat them as flat arrays. The
ability to do

float (*ptr)[3]= flat_ptr;

improves readability and maintainability --a lot. In C99 we now have

int m= blabla;
float (* restrict matrix)[m]= flat_ptr;

as in the non-normative example I quoted, and it's about time too.
--
pa at panix dot com
Jan 6 '08 #6

"Pierre Asselin" <pa@see.signature.invalidwrote in message
cr88192 <cr*****@hotmail.comwrote:
>"Army1987" <ar******@NOSPAM.itwrote in message
news:fl**********@tdi.cu.mi.it...
Ioannis Vranos wrote:

Are the following guaranteed to work always as *C90* code?
[ Treating an int array[10][5] as it were int array[1][50] ]
[ ... ] Unless
there is some implementation on which that fails, I'd not object to it
being allowed.
>I have an example:
consider the C implementation is built on top of a VM framework of some
sort;
this VM does not allow multidimensional arrays as such, but treats the
case
of multidimensional arrays as a nested set of 1D arrays.

I don't see how that affects C. The OP's int array[10][5] has to
be laid out in memory the same way as an int [50]. If the VM or hardware
has some weird facility, the C implementation is not obligated to use it.
possibly, but say the C app implementation is expected to share data with
the other languages that operate on the same VM.

anyways, that it be laid out the same as int[50] is not actually required as
such, only that this is the common practice...

>all works well, as long as we use the array as specified.
going outside this, the implementation may well crash, issue bounds-check
exceptions, ...

It looks like a conforming implementation could stuff bounds
information into fat pointers and trap at runtime. That could be
tolerable to me as an extension, but if the behavior can't be switched
off the an implementation would be disqualified as far as I am
concerned.
on what grounds exactly?
that is doesn't allow one to, technically, violate the standard?...

>
>so, in general, I would personally probably advise against relying on
this
kind of behavior (instead, when needed, faking multidimensional arrays
using
larger 1D arrays, so that the multidimensional case need not be
compromised
as such).

Yeah, if you like ugly code. These days I deal with arrays of 3n floats;
in some parts of the code it is more convenient to view them as nx3
arrays,
in others it is more convenient to treat them as flat arrays. The
ability to do

float (*ptr)[3]= flat_ptr;

improves readability and maintainability --a lot. In C99 we now have

int m= blabla;
float (* restrict matrix)[m]= flat_ptr;

as in the non-normative example I quoted, and it's about time too.
I perfer to stick with the approach of emulating the multidimensional arrays
via a large 1D array.
it is not that bad IMO:

float *ma;
ma=malloc(16*sizeof(float));
memset(ma, 0, 16*sizeof(float));

ma[0*4+0]=1;
ma[1*4+1]=1;
ma[2*4+2]=1;
ma[3*4+3]=1;

this convention extends nicely and easily to a higher number of dimensionas
as well.

>
--
pa at panix dot com

Jan 7 '08 #7
"cr88192" <cr*****@hotmail.comwrites:
"Pierre Asselin" <pa@see.signature.invalidwrote in message
[...]
>I don't see how that affects C. The OP's int array[10][5] has to
be laid out in memory the same way as an int [50]. If the VM or hardware
has some weird facility, the C implementation is not obligated to use it.

possibly, but say the C app implementation is expected to share data with
the other languages that operate on the same VM.

anyways, that it be laid out the same as int[50] is not actually
required as such, only that this is the common practice...
[...]

It's not *directly* required, but I believe it's indirectly required.
Array elements must be allocated consecutively. I don't believe it's
possible for an implementation to lay out
int array_2d[10][5];
and
int array_1d[50];
differently.

But there's not a lot that a program can portably do to take advantage
of that, other than by access both as arrays of unsigned char. Though
array_2d[1][0] and array_2d[0][5] will *usually* refer to the same int
object, the latter, strictly speaking, invokes undefined behavior.
This can cause problems either if the implementation performs
aggressive bounds checking, or if an optimizing compiler generates
"bad" code because it assumes that all array references will be within
declared bounds.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 7 '08 #8
Keith Thompson <ks***@mib.orgwrote:
"cr88192" <cr*****@hotmail.comwrites:

anyways, that it be laid out the same as int[50] is not actually
required as such, only that this is the common practice...
[...]
It's not *directly* required, but I believe it's indirectly required.
Array elements must be allocated consecutively. I don't believe it's
possible for an implementation to lay out
int array_2d[10][5];
and
int array_1d[50];
differently.
That was my impression as well.
But there's not a lot that a program can portably do to take advantage
of that, other than by access both as arrays of unsigned char. Though
array_2d[1][0] and array_2d[0][5] will *usually* refer to the same int
object, the latter, strictly speaking, invokes undefined behavior.
But the OP wasn't breaking that rule, he only referred to array_2d[i][j]
with j<5. None of his uses had any aliasing. The question was
whether it is legal to convert a flat array to a 2d view,

int flat[50];
int (*array_2d)[5]= (int (*)[5]) flat;

and proceed as-if

int array_2d[10][5];

int array_2d[10][5];
int *flat= array_2d[0];
for(i= 0; i<50; i++) {/* use flat[i] */}

and *that* I think is technically illegal, but it's a damn shame.
--
pa at panix dot com
Jan 8 '08 #9
cr88192 <cr*****@hotmail.comwrote:
"Pierre Asselin" <pa@see.signature.invalidwrote in message
cr88192 <cr*****@hotmail.comwrote:

I have an example:
consider the C implementation is built on top of a VM framework of some
sort;
this VM does not allow multidimensional arrays as such, but treats the
case
of multidimensional arrays as a nested set of 1D arrays.
I don't see how that affects C. The OP's int array[10][5] has to
be laid out in memory the same way as an int [50]. If the VM or hardware
has some weird facility, the C implementation is not obligated to use it.
possibly, but say the C app implementation is expected to share data with
the other languages that operate on the same VM.
It can provide extensions to do so, but not pollute the core language.

[ ... ] but if the behavior can't be switched
off the an implementation would be disqualified as far as I am
concerned.
on what grounds exactly?
that is doesn't allow one to, technically, violate the standard?...
On the grounds that it would take a heads-in-the-clouds, ivory-tower,
weasel-wording, loophole-mucking language lawyer with no interest
in practical applications to come up with an implementation like
that. Doesn't fit my tastes, but that's just me.

float (*ptr)[3]= flat_ptr;

improves readability and maintainability --a lot. [ ... ]
I perfer to stick with the approach of emulating the multidimensional arrays
via a large 1D array.
it is not that bad IMO:
float *ma;
ma=malloc(16*sizeof(float));
memset(ma, 0, 16*sizeof(float));
ma[0*4+0]=1;
ma[1*4+1]=1;
ma[2*4+2]=1;
ma[3*4+3]=1;
/* Okay, */
float *flat= malloc(m*n*p*sizeof(flat[0]));
float (*tensor)[n][p]= (void *) flat;

tensor[i][j][k]; /* cool */
flat[i*n*p+j*p+k]; /* ugly */
flat[i*n*p + j*p + k]; /* ugly */
flat[(i*n+j)*p+k];; /* ugly */
flat[(i*n + j)*p + k];; /* ugly */
#define INDEX(i,j,k) ((i)*n*p+(j)*p+(k))
flat[INDEX(i,j,k)] /* desperate */

The uglies stay ugly and error-prone no matter how you tweak the

There is also an efficiency issue. With the flat array notation
the compiler has to be damn good at dependency analysis and strength
reduction to optimize loops over flat[]. With the C99 VLA (and
restrict, which I left out above) the type system supplies the
--
pa at panix dot com
Jan 8 '08 #10
Army1987 wrote:
Ioannis Vranos wrote:
>Are the following guaranteed to work always as *C90* code?
[ Treating an int array[10][5] as it were int array[1][50] ]
That's one of those things for which the standard defines no behavior,
without any reason not to do define one. I'd be very surprised if it
failed, but that would not make an implementation non-conforming. Unless
there is some implementation on which that fails, I'd not object to it
being allowed.
(Another such thing is the struct hack, or printing a nonnegative signed
int with %x. They can fail, but I can't see any way in which they could,
other than the implementation being *intentionally* hostile.)
Using the struct hack, say we define
struct s {
int cost
char name[1];
};

struct s* ps;
int i;
char c;

and dynamically allocate structs with added length for the required name
length. Now access an entry with
c = ps->name[i];

On an 8-bit target, it is more efficient to do 8-bit arithmetic than
multibyte arithmetic. The compiler can see that the maximum valid index of
name is 0, so needn't bother with looking at the upper bytes of i to
compute the effective address. I suppose with an upper index of 0, it
doesn't even need to bother with fetching the index at all!

Similar logic can be used to optimize two dimensional accesses, say of a 30
x 30 char array, knowing that an index can't be bigger than the specified
dimensional limit.

--
Jan 8 '08 #11
Pierre Asselin wrote:
>
.... snip ...
>

int array_2d[10][5];
int *flat= array_2d[0];
for(i= 0; i<50; i++) {/* use flat[i] */}

and *that* I think is technically illegal, but it's a damn shame.
Try: int *flat = &array_2d[0][0];

array_2d[0] is an array of 5 ints.

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

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

Jan 8 '08 #12
CBFalconer wrote:
Pierre Asselin wrote:
... snip ...

int array_2d[10][5];
int *flat= array_2d[0];
for(i= 0; i<50; i++) {/* use flat[i] */}

and *that* I think is technically illegal, but it's a damn shame.

Try: int *flat = &array_2d[0][0];

array_2d[0] is an array of 5 ints.

array2d[0] is an array of 5 ints and it "behaves" (I do not know the
accurate technical term)as a pointer to array_2d[0][0], that is
*array_2d[0] is array_2d[0][0].
Jan 8 '08 #13
Correction:
Ioannis Vranos wrote:
>
>array_2d[0] is an array of 5 ints.

array2d[0] is an array of 5 ints and it "behaves" (I do not know the
accurate technical term)as a pointer to array_2d[0][0], that is
*(array_2d[0]) is array_2d[0][0].
Jan 8 '08 #14
CBFalconer <cb********@yahoo.comwrote:
Pierre Asselin wrote:

int array_2d[10][5];
int *flat= array_2d[0];
Try: int *flat = &array_2d[0][0];
array_2d[0] is an array of 5 ints.
.... and converts to an expression of type "pointer to int".

--
pa at panix dot com
Jan 9 '08 #15
Ioannis Vranos wrote:
Ioannis Vranos wrote:

Correction:
>>array_2d[0] is an array of 5 ints.

array2d[0] is an array of 5 ints and it "behaves" (I do not know
the accurate technical term)as a pointer to array_2d[0][0], that is

*(array_2d[0]) is array_2d[0][0].
No. Don't drop the details. *(array_2d[0]) is a pointer to an
array of 5 ints. array_2d[0][0] is an int. Just one.

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

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

Jan 9 '08 #16
CBFalconer <cb********@yahoo.comwrites:
Ioannis Vranos wrote:
>Ioannis Vranos wrote:

Correction:
>>>array_2d[0] is an array of 5 ints.

array2d[0] is an array of 5 ints and it "behaves" (I do not know
the accurate technical term)as a pointer to array_2d[0][0], that is

*(array_2d[0]) is array_2d[0][0].

No. Don't drop the details. *(array_2d[0]) is a pointer to an
array of 5 ints.
The usual c.l.c style seems to be "chapter and verse, please" but that
always seems too blunt to me. Can you back this up?
array_2d[0][0] is an int. Just one.
Agreed.

Presumably in the context of 'int array_2d[10][5];'.

--
Ben.
Jan 9 '08 #17
CBFalconer wrote:
>Ioannis Vranos wrote:

Correction:
>>>array_2d[0] is an array of 5 ints.
array2d[0] is an array of 5 ints and it "behaves" (I do not know
the accurate technical term)as a pointer to array_2d[0][0], that is
*(array_2d[0]) is array_2d[0][0].

No. Don't drop the details. *(array_2d[0]) is a pointer to an
array of 5 ints. array_2d[0][0] is an int. Just one.

Actually my correction with addition of parentheses was not needed.

Given: int array_2d[10][5];

array_2d behaves like a pointer to an array of 5 ints.
array2d_[0] behaves like a pointer to array_2d[0][0];
Jan 9 '08 #18
Ioannis Vranos wrote:
CBFalconer wrote:
>>Ioannis Vranos wrote:

Correction:

array_2d[0] is an array of 5 ints.
array2d[0] is an array of 5 ints and it "behaves" (I do not know
the accurate technical term)as a pointer to array_2d[0][0], that is
*(array_2d[0]) is array_2d[0][0].

No. Don't drop the details. *(array_2d[0]) is a pointer to an
array of 5 ints. array_2d[0][0] is an int. Just one.

Actually my correction with addition of parentheses was not needed.

Given: int array_2d[10][5];

array_2d behaves like a pointer to an array of 5 ints.
array2d_[0] behaves like a pointer to array_2d[0][0];
No it isn't. For example (remembering that array_2d[0][0] is an
int) try the following:

[1] c:\c\junk>cat junk.c
#include <stdio.h>

int testfunct(void) {
int array_2d[10][5] = {{0}};
int test;

printf("sizeof array_2d[0] is %d\n",
(int)(sizeof array_2d[0]));
test = array_2d[0];
return 1;
}

int main(void) {testfunct(); return 0;}

[1] c:\c\junk>cc junk.c
junk.c: In function `testfunct':
junk.c:9: warning: assignment makes integer from pointer without
a cast

[1] c:\c\junk>a
sizeof array_2d[0] is 20

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

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

Jan 9 '08 #19
CBFalconer wrote:
>
[1] c:\c\junk>a
sizeof array_2d[0] is 20
int array_2d[10][5];
I do not understand what you mean. array_2d[0] is an array of 5 ints and
it also behaves as a pointer to the first element of that array, that is
as a pointer to array[0][0].

That is, *array[0] is array[0][0].

Jan 9 '08 #20
CBFalconer <cb********@yahoo.comwrites:
Ioannis Vranos wrote:
>CBFalconer wrote:
>>>Ioannis Vranos wrote:

Correction:

>array_2d[0] is an array of 5 ints.
array2d[0] is an array of 5 ints and it "behaves" (I do not know
the accurate technical term)as a pointer to array_2d[0][0], that is
*(array_2d[0]) is array_2d[0][0].

No. Don't drop the details. *(array_2d[0]) is a pointer to an
array of 5 ints. array_2d[0][0] is an int. Just one.

Actually my correction with addition of parentheses was not needed.

Given: int array_2d[10][5];

array_2d behaves like a pointer to an array of 5 ints.
array2d_[0] behaves like a pointer to array_2d[0][0];

No it isn't. For example (remembering that array_2d[0][0] is an
int) try the following:

[1] c:\c\junk>cat junk.c
#include <stdio.h>

int testfunct(void) {
int array_2d[10][5] = {{0}};
int test;

printf("sizeof array_2d[0] is %d\n",
(int)(sizeof array_2d[0]));
test = array_2d[0];
The compiler diagnostic that you quote shows that array_2d[0] can not
be assigned to an int, but I can't see how that helps clarify things.
The output of the printf shows that array_2d[0] is not converted to
pointer when it is the operand of sizeof, but if that was your point
would it not have been simpler just to say so, or at least to
illustrate it with a correct program? The fact you post a diagnostic
suggests you think it illustrates something.

Ioannis: Your term "behaves" is not a bad one. You state you don't
know the correct terminology, but the trouble is there is no simple
way to say what you are trying to say. The standard puts it like
this:

Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type "array of type" is converted to an
expression with type "pointer to type" that points to the initial
element of the array object

but it is very tedious to keep saying that! The upshot is that one
can't always talk about the type of a part of expression in C. You
need to see the whole thing, or at least to keep saying "unless this
is the operand of...".
return 1;
}

int main(void) {testfunct(); return 0;}

[1] c:\c\junk>cc junk.c
junk.c: In function `testfunct':
junk.c:9: warning: assignment makes integer from pointer without
a cast
--
Ben.
Jan 9 '08 #21
CBFalconer <cb********@yahoo.comwrote:
Keith Thompson wrote:
[ conversion of <array of Tto <pointer to T]

(Didn't we have this discussion just recently?)
I wasn't trying for a discussion, just correcting Ioannis'
Chuck, what misconception was that ?
--
pa at panix dot com
Jan 10 '08 #22
On Wed, 09 Jan 2008 14:54:46 +0200, Ioannis Vranos <jo**@no.spam>
wrote:
>CBFalconer wrote:
>>Ioannis Vranos wrote:

Correction:

array_2d[0] is an array of 5 ints.
array2d[0] is an array of 5 ints and it "behaves" (I do not know
the accurate technical term)as a pointer to array_2d[0][0], that is
*(array_2d[0]) is array_2d[0][0].

No. Don't drop the details. *(array_2d[0]) is a pointer to an
array of 5 ints. array_2d[0][0] is an int. Just one.

Actually my correction with addition of parentheses was not needed.

Given: int array_2d[10][5];

array_2d behaves like a pointer to an array of 5 ints.
array2d_[0] behaves like a pointer to array_2d[0][0];
Why the inconsistency in your description - one with a type and one
with an object?

The rule is very straight forward: "Except when it is the operand of
the sizeof operator or the unary & operator, or is a string literal
used to initialize an array, an expression that has type ‘‘array of
type’’ is converted to an expression with type ‘‘pointer to type’’
that points to the initial element of the array object..."

The expression
array_2d
is converted to a pointer to array_2d[0] which has type pointer to
array of 5 int and which is expressed syntactically as
&array_2d[0]
which has type
int (*)[5]

The expression
array_2d[0]
is converted to a pointer to array_2d[0][0] which has type pointer to
int and which is expressed syntactically as
&array_2d[0][0]
which has type
int *
Remove del for email
Jan 13 '08 #23
Barry Schwarz wrote:
>
[Fixed the typos a bit]
>Actually my correction with addition of parentheses was not needed.

Given: int array[10][5];

array behaves like a pointer to an array of 5 ints.
array[0] behaves like a pointer to array[0][0];

Why the inconsistency in your description - one with a type and one
with an object?

The rule is very straight forward: "Except when it is the operand of
the sizeof operator or the unary & operator, or is a string literal
used to initialize an array, an expression that has type ‘‘array of
type’’ is converted to an expression with type ‘‘pointer to type’’
that points to the initial element of the array object..."

The expression
array
is converted to a pointer to array[0] which has type pointer to
array of 5 int and which is expressed syntactically as
&array[0]
which has type
int (*)[5]

The expression
array[0]
is converted to a pointer to array[0][0] which has type pointer to
int and which is expressed syntactically as
&array[0][0]
which has type
int *

Given the above you mentioned, and AFAIK, array[0] *is* an array of 5
ints, which also behaves like a pointer to an array of 5 ints.
Jan 13 '08 #24
Corrected:
Ioannis Vranos wrote:
Barry Schwarz wrote:
>

[Fixed the typos a bit]
>Actually my correction with addition of parentheses was not needed.
>>
>Given: int array[10][5];
>>
>array behaves like a pointer to an array of 5 ints.
>array[0] behaves like a pointer to array[0][0];
>
Why the inconsistency in your description - one with a type and one
with an object?
>
The rule is very straight forward: "Except when it is the operand of
the sizeof operator or the unary & operator, or is a string literal
used to initialize an array, an expression that has type ‘‘array of
type’’ is converted to an expression with type ‘‘pointer to type’’
that points to the initial element of the array object..."
>
The expression
array
is converted to a pointer to array[0] which has type pointer to
array of 5 int and which is expressed syntactically as
&array[0]
which has type
int (*)[5]
>
The expression
array[0]
is converted to a pointer to array[0][0] which has type pointer to
int and which is expressed syntactically as
&array[0][0]
which has type
int *
>

Given the above you mentioned, and AFAIK, array is an array of [10][5]
elements which behaves like a pointer to its first element, that is like
a pointer to array[0], that is, like a pointer to an array of 5 elements.

array[0] is an array of 5 elements, which behaves like a pointer to its
first element, that is like an int *.
array[0] *is* an array of 5
ints, which also behaves like a pointer to the first element.
Jan 13 '08 #25
Corrected again (my last version):

Ioannis Vranos wrote:
>
Ioannis Vranos wrote:
>Barry Schwarz wrote:
> >

[Fixed the typos a bit]
> >Actually my correction with addition of parentheses was not needed.

Given: int array[10][5];

array behaves like a pointer to an array of 5 ints.
array[0] behaves like a pointer to array[0][0];

Why the inconsistency in your description - one with a type and one
with an object?

The rule is very straight forward: "Except when it is the operand of
the sizeof operator or the unary & operator, or is a string literal
used to initialize an array, an expression that has type ‘‘array of
type’’ is converted to an expression with type ‘‘pointer to type’’
that points to the initial element of the array object..."

The expression
array
is converted to a pointer to array[0] which has type pointer to
array of 5 int and which is expressed syntactically as
&array[0]
which has type
int (*)[5]

The expression
array[0]
is converted to a pointer to array[0][0] which has type pointer to
int and which is expressed syntactically as
&array[0][0]
which has type
int *

Given the above you mentioned, and AFAIK, array is an array of [10][5]
elements which behaves like a pointer to its first element, that is like
a pointer to array[0], that is, like a pointer to an array of 5 elements.

array[0] is an array of 5 elements, which behaves like a pointer to its
first element, that is like an int *.
Jan 13 '08 #26
Ioannis Vranos <jo**@no.spamwrites:
Barry Schwarz wrote:
[Fixed the typos a bit]
>>Actually my correction with addition of parentheses was not needed.

Given: int array[10][5];

array behaves like a pointer to an array of 5 ints.
array[0] behaves like a pointer to array[0][0];

Why the inconsistency in your description - one with a type and one
with an object?

The rule is very straight forward: "Except when it is the operand of
the sizeof operator or the unary & operator, or is a string literal
used to initialize an array, an expression that has type â€˜â€˜array of
typeâ€™â€™ is converted to an expression with type â€˜â€˜pointer to typeâ€™â€™
that points to the initial element of the array object..."
[...]
Given the above you mentioned, and AFAIK, array[0] *is* an array of 5
ints, which also behaves like a pointer to an array of 5 ints.
I think the phrase "behaves like" is causing problems.

I think that what's really causing problems (at least for me) is
a bit of ambiguity about the meaning of the name of something.

Let's take a simpler example, to avoid any confusion about
multidimensional arrays. Given:

int foo[20];

When I talk about ``foo'' in an English text discussion, am I
referring to the declared object whose name is ``foo'', or am I
talking about ``foo'' as a C expression?

The object whose name is ``foo'' is an array; it's not a pointer, and
it doesn't act like a pointer.

The C expression ``foo'', which is a primary expression (specifically
an identifier) *refers* to the object, but as an expression it can be
either of array type (if it's the operand of a unary "sizeof" or "&")
or be converted to pointer type (in any other context).

Going back to the original example, if we're talking about the
*object* array[0], it's an array object. It doesn't behave like a
pointer. In particular, it doesn't behave like a pointer object;
there is no pointer object here. But if we're talking about the
*expression" array[0], it's often implicitly converted to a pointer;
in that sense, you could say that it (sometimes!) "behaves like" a
pointer.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 13 '08 #27

### This discussion thread is closed

Replies have been disabled for this discussion.