Velocity Reviews > Pointer to inside an array

Pointer to inside an array

Alok Singhal
Guest
Posts: n/a

 12-15-2009
Hi,

Let's say I have:

int a[20] = {0};

Is the declaration below legal according to C89?

int (*p)[5] = (int (*)[5])(a+6);

mohangupta13
Guest
Posts: n/a

 12-15-2009
On Dec 15, 4:03*pm, Alok Singhal <(E-Mail Removed)> wrote:
> Hi,
>
> Let's say I have:
>
> int a[20] = {0};
>
> Is the declaration below legal according to C89?
>
> int (*p)[5] = (int (*)[5])(a+6);

As far as i think (i am not 100% certain though) its legal. But in
this case only (p+2)[3] can be safely addressed for storing values.

Mohan

annalissa
Guest
Posts: n/a

 12-15-2009
On Dec 15, 12:24*pm, mohangupta13 <(E-Mail Removed)> wrote:
> On Dec 15, 4:03*pm, Alok *Singhal <(E-Mail Removed)> wrote:> Hi,
>
> > Let's say I have:

>
> > int a[20] = {0};

>
> > Is the declaration below legal according to C89?

>
> > int (*p)[5] = (int (*)[5])(a+6);

consider this program:-

#include<stdio.h>
#include<stdlib.h>

int main(void)
{

int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,2 0};

int (*p)[5] = (int(*)[5])(a+6);

printf("\n %d",(*p)[0]);

return(EXIT_SUCCESS);
}

compile this program as gcc -g -ansi -pedantic -o progname
progname.c , then decide for yourself

> As far as i think (i am not 100% certain though) its legal. But in
> this case only (p+2)[3] can be safely addressed for storing values.

what do you mean by the statement that (p+2)[3] can be safely
addressed for storing values. ???

mohangupta13
Guest
Posts: n/a

 12-15-2009
On Dec 16, 12:25*am, annalissa <(E-Mail Removed)> wrote:
> On Dec 15, 12:24*pm, mohangupta13 <(E-Mail Removed)> wrote:
>
> > On Dec 15, 4:03*pm, Alok *Singhal <(E-Mail Removed)> wrote:> Hi,

>
> > > Let's say I have:

>
> > > int a[20] = {0};

>
> > > Is the declaration below legal according to C89?

>
> > > int (*p)[5] = (int (*)[5])(a+6);

>
> consider this program:-
>
> #include<stdio.h>
> #include<stdlib.h>
>
> int main(void)
> {
>
> *int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,2 0};
>
> * int (*p)[5] = (int(*)[5])(a+6);
>
> * printf("\n %d",(*p)[0]);
>
> * return(EXIT_SUCCESS);
>
> }
>
> compile this program as gcc -g -ansi -pedantic -o progname
> progname.c , then decide for yourself
>
> > As far as i think (i am not 100% certain though) its legal. But in
> > this case only (p+2)[3] can be safely addressed for storing values.

>
> what do you mean by the statement that (p+2)[3] can be safely
> addressed for storing values. ???

well i meant that the last value accessible through p is (p+2)[3] it
should be the value at a[19].

Alok Singhal
Guest
Posts: n/a

 12-15-2009
On Tue, 15 Dec 2009 11:25:14 -0800, annalissa wrote:
> consider this program:-
>
> #include<stdio.h>
> #include<stdlib.h>
>
> int main(void)
> {
>
> int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,2 0};
>
> int (*p)[5] = (int(*)[5])(a+6);
>
> printf("\n %d",(*p)[0]);
>
> return(EXIT_SUCCESS);
> }
>
> compile this program as gcc -g -ansi -pedantic -o progname progname.c ,
> then decide for yourself

Yes, gcc doesn't give any warnings, but we are casting p to what we
want. If we remove the cast, gcc does give a warning saying:
"initialization from incompatible pointer type". I understand that the
initialization is from an incompatible pointer type, so I *think* this
means that the behavior is undefined. But I am not sure.

Thanks,
Alok

Ben Bacarisse
Guest
Posts: n/a

 12-15-2009
mohangupta13 <(E-Mail Removed)> writes:

> On Dec 16, 12:25Â*am, annalissa <(E-Mail Removed)> wrote:
>> On Dec 15, 12:24Â*pm, mohangupta13 <(E-Mail Removed)> wrote:
>>
>> > On Dec 15, 4:03Â*pm, Alok Â*Singhal <(E-Mail Removed)> wrote:> Hi,

>>
>> > > Let's say I have:

>>
>> > > int a[20] = {0};

>>
>> > > Is the declaration below legal according to C89?

>>
>> > > int (*p)[5] = (int (*)[5])(a+6);

<snip>
>> > As far as i think (i am not 100% certain though) its legal.

"Legal" is an odd word in this context. The conversion between the
two pointer types is implementation defined so I suppose pretty much
any result is possible though there is an "obvious" conversion.

>> > But in
>> > this case only (p+2)[3] can be safely addressed for storing values.

>>
>> what do you mean by the statement that (p+2)[3] can be safely
>> addressed for storing values. ???

>
> well i meant that the last value accessible through p is (p+2)[3] it
> should be the value at a[19].

(p+2)[3] and a[19] have different types. You probably meant
(*(p+2))[3] but that is simpler to right as p[2][3].

--
Ben.

Barry Schwarz
Guest
Posts: n/a

 12-16-2009
On Tue, 15 Dec 2009 20:06:07 +0000 (UTC), Alok Singhal
<(E-Mail Removed)> wrote:

>On Tue, 15 Dec 2009 11:25:14 -0800, annalissa wrote:
>> consider this program:-
>>
>> #include<stdio.h>
>> #include<stdlib.h>
>>
>> int main(void)
>> {
>>
>> int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,2 0};
>>
>> int (*p)[5] = (int(*)[5])(a+6);
>>
>> printf("\n %d",(*p)[0]);
>>
>> return(EXIT_SUCCESS);
>> }
>>
>> compile this program as gcc -g -ansi -pedantic -o progname progname.c ,
>> then decide for yourself

>
>Yes, gcc doesn't give any warnings, but we are casting p to what we
>want. If we remove the cast, gcc does give a warning saying:
>"initialization from incompatible pointer type". I understand that the
>initialization is from an incompatible pointer type, so I *think* this
>means that the behavior is undefined. But I am not sure.

Think again. The purpose of the cast is not to silence the warning
but to coerce the value of the expression to a compatible type and
eliminate the condition that requires a diagnostic.

The code
unsigned char *ptr = (unsigned char*)(a+6);
will produce the exact same warning without the cast yet the
initialization is perfectly well defined as written.

--
Remove del for email

Peter Nilsson
Guest
Posts: n/a

 12-16-2009
annalissa <(E-Mail Removed)> wrote:
> mohangupta13 <(E-Mail Removed)> wrote:
> > Alok *Singhal <(E-Mail Removed)> wrote:> Hi,
> > > Let's say I have:
> > >
> > > int a[20] = {0};
> > >
> > > Is the declaration below legal according to C89?
> > >
> > > int (*p)[5] = (int (*)[5])(a+6);

Depends on wheather a+6 is properly aligned for an int(*)[5].
If not, then no, it's not valid. I don't believe the standard
guarantees you can dereference it, only convert it back to an
int *. Also, you are accessing part of an object using a
different type to the effective type.

> consider this program:-

<snip>
>
> compile this program as gcc -g -ansi -pedantic -o progname
> progname.c , then decide for yourself

That something compiles without a diagnostic under gcc does not
mean it is correct. E.g. ...

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

--
Peter

annalissa
Guest
Posts: n/a

 12-16-2009
On Dec 15, 11:00*pm, Peter Nilsson <(E-Mail Removed)> wrote:
> annalissa <(E-Mail Removed)> wrote:
> > mohangupta13 <(E-Mail Removed)> wrote:
> > > Alok *Singhal <(E-Mail Removed)> wrote:> Hi,
> > > > Let's say I have:

>
> > > > int a[20] = {0};

>
> > > > Is the declaration below legal according to C89?

>
> > > > int (*p)[5] = (int (*)[5])(a+6);

>
> Depends on wheather a+6 is properly aligned for an int(*)[5].
> If not, then no, it's not valid. I don't believe the standard
> guarantees you can dereference it, only convert it back to an
> int *. Also, you are accessing part of an object using a
> different type to the effective type.
>
>
>
> > consider this program:-

> <snip>
>
> > compile this program as gcc -g -ansi -pedantic -o progname
> > progname.c , then decide for yourself

>
> That something compiles without a diagnostic under gcc does not
> mean it is correct. E.g. ...
>
> * int main(void) { return * (int *) 0; }

what is the diagnostic that i am missing ..??

Alok Singhal
Guest
Posts: n/a

 12-16-2009
On Tue, 15 Dec 2009 18:31:44 -0800, Barry Schwarz wrote:
> On Tue, 15 Dec 2009 20:06:07 +0000 (UTC), Alok Singhal
> <(E-Mail Removed)> wrote:
>>>
>>> int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,2 0};
>>>
>>> int (*p)[5] = (int(*)[5])(a+6);

>
> Think again. The purpose of the cast is not to silence the warning but
> to coerce the value of the expression to a compatible type and eliminate
> the condition that requires a diagnostic.
>
> The code
> unsigned char *ptr = (unsigned char*)(a+6);
> will produce the exact same warning without the cast yet the
> initialization is perfectly well defined as written.

Thanks. This is what I was looking for. I should have read the standard
more carefully as well. So 6.3.2.3p7 (N1336) applies here:

A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the resulting
pointer is not correctly aligned for the pointed-to type, the behavior
is undefined. Otherwise, when converted back again, the result shall
compare equal to the original pointer.

There is no guarantee that int (*)[5] is correctly aligned for int *, and
even if it is, the standard makes no guarantees about dereferencing such
a pointer.

-Alok