Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

c.l.c. faq defects?

1 view
Skip to first unread message

Ioannis Vranos

unread,
Dec 10, 2001, 5:42:46 PM12/10/01
to
I know that the subject is a big word but i just came across
http://www.eskimo.com/~scs/C-faq/q6.16.html

where i have the following comments:


a) It uses a lot unnecessary casts.


b) Towards the end it writes:

"Finally, you could use pointers to arrays:

int (*array4)[NCOLUMNS] =
(int (*)[NCOLUMNS])malloc(nrows * sizeof(*array4));

but the syntax starts getting horrific and at most one dimension may be
specified at run time".


At first this is incomplete. It doesn't create the int elements.

Secondly shouldn't this "NCOLUMNS" be "NROWS" and that "nrows" be
"NCOLUMNS"?


Except of the above isn't the following both valid and safe?


int (*array)[ROWS]=malloc(ROWS*COLUMNS*sizeof(**array));


Piece of code that compiles ok:


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

#define COLUMNS 10
#define ROWS 20

int main(void)
{
int (*array)[ROWS]=malloc(ROWS*COLUMNS*sizeof(**array));

int i, j;

for(i=0; i<ROWS; i++)
for(j=0; j<COLUMNS; j++)
array[i][j]=j;

return 0;
}

Ioannis
--
* Ioannis Vranos
* Programming pages: http://www.noicys.f2s.com
* Alternative URL: http://run.to/noicys

Ioannis Vranos

unread,
Dec 10, 2001, 5:45:01 PM12/10/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message
news:10080241...@athprx02.forthnet.gr...

> I know that the subject is a big word but i just came across
>
> Secondly shouldn't this "NCOLUMNS" be "NROWS" and that "nrows" be
> "NCOLUMNS"?

I rush to correct this. The code is ok on this aspect.

Ioannis Vranos

unread,
Dec 10, 2001, 5:47:21 PM12/10/01
to
I made some important mistakes and sorry all about this, so i repost it
corrected.

I know that the subject is a big word but i just came across
http://www.eskimo.com/~scs/C-faq/q6.16.html

where i have the following comments:


a) It uses a lot unnecessary casts.


b) Towards the end it writes:

"Finally, you could use pointers to arrays:

int (*array4)[NCOLUMNS] =
(int (*)[NCOLUMNS])malloc(nrows * sizeof(*array4));

but the syntax starts getting horrific and at most one dimension may be
specified at run time".


At first this is incomplete. It doesn't create the int elements.

Except of the above isn't the following both valid and safe?


int (*array)[COLUMNS]=malloc(ROWS*COLUMNS*sizeof(**array));


Piece of code that compiles ok:

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

#define COLUMNS 10
#define ROWS 20

int main(void)
{
int (*array)[COLUMNS]=malloc(ROWS*COLUMNS*sizeof(**array));

Barry Schwarz

unread,
Dec 10, 2001, 9:19:34 PM12/10/01
to
On Tue, 11 Dec 2001 00:47:21 +0200, "Ioannis Vranos"
<noicys@no_spam.yahoo.com> wrote:
snip

> b) Towards the end it writes:
>
> "Finally, you could use pointers to arrays:
>
> int (*array4)[NCOLUMNS] =
> (int (*)[NCOLUMNS])malloc(nrows * sizeof(*array4));
>
> but the syntax starts getting horrific and at most one dimension may be
> specified at run time".
>
>
> At first this is incomplete. It doesn't create the int elements.
>
> Except of the above isn't the following both valid and safe?
>
>
> int (*array)[COLUMNS]=malloc(ROWS*COLUMNS*sizeof(**array));
If NCOLUMNS is equal to COLUMNS, sizeof *array4 is identical to
COLUMNS * sizeof **array so the two would be equivalent.

>
>
> Piece of code that compiles ok:
>
>#include <stdio.h>
>#include <stdlib.h>
>
>#define COLUMNS 10
>#define ROWS 20
>
>int main(void)
>{
> int (*array)[COLUMNS]=malloc(ROWS*COLUMNS*sizeof(**array));
>
> int i, j;
>
> for(i=0; i<ROWS; i++)
> for(j=0; j<COLUMNS; j++)
> array[i][j]=j;
>
>
>
> return 0;
>}
Yes this will work. It is more typing and harder to understand,
especially when you go back and read it six months later, but it will
work.


<<Remove the del for email>>

Ioannis Vranos

unread,
Dec 10, 2001, 10:26:01 PM12/10/01
to
"Barry Schwarz" <schw...@deloz.net> wrote in message
news:9v3qfm$bii$1...@216.39.135.99...

> Yes this will work. It is more typing and harder to understand,
> especially when you go back and read it six months later, but it will
> work.

Cool. From this i got confused than a ** pointer can do the same, but i
missed the fact that a ** pointer doesn't "know" the length of every
"row" so we couldn't apply the subscript operators.

Dan Pop

unread,
Dec 11, 2001, 8:27:52 AM12/11/01
to

>I made some important mistakes and sorry all about this, so i repost it
>corrected.
>
> I know that the subject is a big word but i just came across
> http://www.eskimo.com/~scs/C-faq/q6.16.html
>
> where i have the following comments:
>
>
> a) It uses a lot unnecessary casts.

This is a known issue. The FAQ was developed to be K&R C compatible,
because K&R C was still relevant at the time. The casts are required
in K&R C.

> b) Towards the end it writes:
>
> "Finally, you could use pointers to arrays:
>
> int (*array4)[NCOLUMNS] =
> (int (*)[NCOLUMNS])malloc(nrows * sizeof(*array4));
>
> but the syntax starts getting horrific and at most one dimension may be
> specified at run time".
>
>
> At first this is incomplete. It doesn't create the int elements.

???

It does allocate the int elements. The question answered was:

6.16: How can I dynamically allocate a multidimensional array?

> Except of the above isn't the following both valid and safe?
>
>
> int (*array)[COLUMNS]=malloc(ROWS*COLUMNS*sizeof(**array));

It's less readable than the FAQ version, which follows the common
practice of dynamically allocating arrays: malloc's argument is the
number of allocated objects times the size of an object.

Dan
--
Dan Pop
CERN, IT Division
Email: Dan...@cern.ch
Mail: CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland

Ioannis Vranos

unread,
Dec 11, 2001, 8:51:09 AM12/11/01
to
"Dan Pop" <Dan...@cern.ch> wrote in message
news:9v51ko$ei$1...@sunnews.cern.ch...

>
> > b) Towards the end it writes:
> >
> > "Finally, you could use pointers to arrays:
> >
> > int (*array4)[NCOLUMNS] =
> > (int (*)[NCOLUMNS])malloc(nrows * sizeof(*array4));
> >
> > but the syntax starts getting horrific and at most one dimension may
be
> > specified at run time".
> >
> >
> > At first this is incomplete. It doesn't create the int elements.
>
> ???
>
> It does allocate the int elements. The question answered was:

Yes you are right, now i realized it. This is too cryptic according to
me (sizeof(*array)==NCOLUMNS*sizeof(int)).


> 6.16: How can I dynamically allocate a multidimensional array?
>
> > Except of the above isn't the following both valid and safe?
> >
> >
> > int (*array)[COLUMNS]=malloc(ROWS*COLUMNS*sizeof(**array));
>
> It's less readable than the FAQ version, which follows the common
> practice of dynamically allocating arrays: malloc's argument is the
> number of allocated objects times the size of an object.


Well it is more readable, but we will not argue about that, it is a
religious issue. :)

Dan Pop

unread,
Dec 11, 2001, 10:57:31 AM12/11/01
to

>"Dan Pop" <Dan...@cern.ch> wrote in message
>news:9v51ko$ei$1...@sunnews.cern.ch...
>>
>> > b) Towards the end it writes:
>> >
>> > "Finally, you could use pointers to arrays:
>> >
>> > int (*array4)[NCOLUMNS] =
>> > (int (*)[NCOLUMNS])malloc(nrows * sizeof(*array4));
>> >
>> > but the syntax starts getting horrific and at most one dimension may
>be
>> > specified at run time".
>> >
>> >
>> > At first this is incomplete. It doesn't create the int elements.
>>
>> ???
>>
>> It does allocate the int elements. The question answered was:
>
>Yes you are right, now i realized it. This is too cryptic according to
>me (sizeof(*array)==NCOLUMNS*sizeof(int)).

This is because you're not familiar with pointers to arrays.

>> 6.16: How can I dynamically allocate a multidimensional array?
>>
>> > Except of the above isn't the following both valid and safe?
>> >
>> >
>> > int (*array)[COLUMNS]=malloc(ROWS*COLUMNS*sizeof(**array));
>>
>> It's less readable than the FAQ version, which follows the common
>> practice of dynamically allocating arrays: malloc's argument is the
>> number of allocated objects times the size of an object.
>
>Well it is more readable,

It might be more readable to YOU, because you're not familiar with
pointers to arrays.

The malloc call conceptually allocates an array of arrays, not a
bidimensional array of int's (strictly speaking, such a thing doesn't
even exist in C). So, the most natural way to express the size is
as explained in my previous post.

Ioannis Vranos

unread,
Dec 11, 2001, 3:55:42 PM12/11/01
to
"Dan Pop" <Dan...@cern.ch> wrote in message
news:9v5adb$5oq$1...@sunnews.cern.ch...

> >> > b) Towards the end it writes:
> >> >
> >> > "Finally, you could use pointers to arrays:
> >> >
> >> > int (*array4)[NCOLUMNS] =
> >> > (int (*)[NCOLUMNS])malloc(nrows * sizeof(*array4));
> >> >
> >> > but the syntax starts getting horrific and at most one dimension
may
> >be
> >> > specified at run time".
> >> >
> >> >
> >> > At first this is incomplete. It doesn't create the int elements.
> >>
> >> ???
> >>
> >> It does allocate the int elements. The question answered was:
> >
> >Yes you are right, now i realized it. This is too cryptic according
to
> >me (sizeof(*array)==NCOLUMNS*sizeof(int)).
>
> This is because you're not familiar with pointers to arrays.


Now i am thinking it, isn't allocating NCOLUMNS int * and not int?


>
> It might be more readable to YOU, because you're not familiar with
> pointers to arrays.


Basically i think that i am quite familiar.


> The malloc call conceptually allocates an array of arrays, not a
> bidimensional array of int's (strictly speaking, such a thing doesn't
> even exist in C). So, the most natural way to express the size is
> as explained in my previous post.


If i am right and it allocates int * and not ints, isn't my approach
more space efficient?

Ioannis Vranos

unread,
Dec 11, 2001, 3:57:28 PM12/11/01
to
I made a mistake, so i repost.


"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message

news:10081041...@athprx02.forthnet.gr...


> "Dan Pop" <Dan...@cern.ch> wrote in message
news:9v5adb$5oq$1...@sunnews.cern.ch...
> >> > b) Towards the end it writes:
> >> >
> >> > "Finally, you could use pointers to arrays:
> >> >
> >> > int (*array4)[NCOLUMNS] =
> >> > (int (*)[NCOLUMNS])malloc(nrows * sizeof(*array4));
> >> >

Now i am thinking it, isn't allocating nrows int * and not int?

Micah Cowan

unread,
Dec 11, 2001, 9:31:05 PM12/11/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> writes:

> > It might be more readable to YOU, because you're not familiar with
> > pointers to arrays.
>
>
> Basically i think that i am quite familiar.

What you think and what is true seem frequently to be entirely
different things. You have proven consistently that you haven't got
the foggiest idea as to the difference between arrays and pointers,
particularly with regard to multidimensional arrays vs. pointers to
pointers.

Micah

willem veenhoven

unread,
Dec 12, 2001, 7:47:18 AM12/12/01
to
Ioannis Vranos wrote:
>
> Micah Cowan:
> For example at int array[0][0], array behaves like a **
> pointer to array[0] which in turn behaves like a pointer to
> array[0][0].

Hmm .. I guess Micah is right. Can you now please stop this
endless sequence of idiotic messages, or do we all have to
migrate to the same newsserver Chris seems to be using?

willem

Ioannis Vranos

unread,
Dec 12, 2001, 7:06:32 AM12/12/01
to
"Micah Cowan" <mi...@cowanbox.com> wrote in message
news:yu8d71l...@mcowan-linux.transmeta.com...


The difference between arrays and pointers. An array behaves like a
pointer to the first element which can't point somewhere else. A
multidimensional array behaves like a ** pointer which can't point
somewhere else. For example at int array[0][0], array behaves like a **


pointer to array[0] which in turn behaves like a pointer to array[0][0].

The only misconception i had is that we could use an ** with
2-dimension subscript operators when we asigned to it the address
"stored" in array (of array[0][0]). And this was apparent that it can't
be done.

Ioannis Vranos

unread,
Dec 12, 2001, 7:09:22 AM12/12/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message
news:10081587...@athprx02.forthnet.gr...

>
> The difference between arrays and pointers. An array behaves like a
> pointer to the first element which can't point somewhere else. A
> multidimensional array behaves like a ** pointer which can't point
> somewhere else. For example at int array[0][0], array behaves like a
**
int
arrray[10][10]

> pointer to array[0] which in turn behaves like a pointer to
array[0][0].

Or better it behaves like int (*)[10] which is something like a
specialized int ** pointer (it knows the number of elements of each
row).


> The only misconception i had is that we could use an ** with
> 2-dimension subscript operators when we asigned to it the address
> "stored" in array (of array[0][0]). And this was apparent that it
can't

array[10][10]

Ioannis Vranos

unread,
Dec 12, 2001, 7:12:40 AM12/12/01
to
"Micah Cowan" <mi...@cowanbox.com> wrote in message
news:yu8d71l...@mcowan-linux.transmeta.com...


Because i wrote it in a hurry and made some light mistakes here we go:


The difference between arrays and pointers: An array behaves like a


pointer to the first element which can't point somewhere else. A
multidimensional array behaves like a ** pointer which can't point

somewhere else. For example at int array[10][10], "array" behaves like a
**


pointer to array[0] which in turn behaves like a pointer to array[0][0].

Or better, "array" behaves like an int(*)[10] pointer.


The only misconception i had is that we could use an ** with
2-dimension subscript operators when we asigned to it the address
"stored" in array (of array[0][0]). And this was apparent that it can't

be done.

Ioannis Vranos

unread,
Dec 12, 2001, 7:47:34 AM12/12/01
to
"willem veenhoven" <wil...@veenhoven.com> wrote in message
news:3C1751D6...@veenhoven.com...

>
> Hmm .. I guess Micah is right. Can you now please stop this
> endless sequence of idiotic messages, or do we all have to
> migrate to the same newsserver Chris seems to be using?

Eheheh, ok, i cease discussing this topic. :)

Micah Cowan

unread,
Dec 12, 2001, 3:13:45 PM12/12/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> writes:

> "Micah Cowan" <mi...@cowanbox.com> wrote in message
> news:yu8d71l...@mcowan-linux.transmeta.com...
> > "Ioannis Vranos" <noicys@no_spam.yahoo.com> writes:
> >
> > > > It might be more readable to YOU, because you're not familiar with
> > > > pointers to arrays.
> > >
> > >
> > > Basically i think that i am quite familiar.
> >
> > What you think and what is true seem frequently to be entirely
> > different things. You have proven consistently that you haven't got
> > the foggiest idea as to the difference between arrays and pointers,
> > particularly with regard to multidimensional arrays vs. pointers to
> > pointers.
>
>
> The difference between arrays and pointers. An array behaves like a
> pointer to the first element which can't point somewhere else. A
> multidimensional array behaves like a ** pointer which can't point
> somewhere else.

You just proved my point again. As several people, including myself,
have already pointed out, a multidimensional array has *NOTHING AT
ALL* to do with double pointers. I've had it. I'm not reading any of
your posts any more until you decide to start reading the responses we
give you.

> For example at int array[0][0], array behaves like a **
> pointer to array[0] which in turn behaves like a pointer to array[0][0].

First part *right* (or nearly), second part *wrong*.

> The only misconception i had is that we could use an ** with
> 2-dimension subscript operators when we asigned to it the address
> "stored" in array (of array[0][0]).

No, you are clearly still loaded with misconceptions. I'm not trying
to insult you, or brush you off - it really is my desire to help
people learn on this group; but I can't waste my time on people who
don't read what a score of regulars have spent their valuable time
writing for them.

(Guess I shoulda plonked a while ago, but I'm still nervous he's gonna
give some bizarre advice to a newbie that'll believe him. I'll leave
that up to RH, LK and CT, who habitually sacrifice themselves for this
greater good ;) - I don't have time)

Micah

Ioannis Vranos

unread,
Dec 12, 2001, 3:59:56 PM12/12/01
to
"Micah Cowan" <mi...@cowanbox.com> wrote in message
news:yu8pu5k...@mcowan-linux.transmeta.com...

> >
> > The difference between arrays and pointers. An array behaves like a
> > pointer to the first element which can't point somewhere else. A
> > multidimensional array behaves like a ** pointer which can't point
> > somewhere else.
>
> You just proved my point again. As several people, including myself,
> have already pointed out, a multidimensional array has *NOTHING AT
> ALL* to do with double pointers. I've had it. I'm not reading any of

We have the code:


#include <stdio.h>


int main(void)
{
int array[10][10];
int *p=array;


return 0;
}

Results from BCC32:

Warning W8075 temp.c 7: Suspicious pointer conversion in function main

That means that "array" doesn't behave as an int *. So explain me please
like what pointer type array behaves.


> your posts any more until you decide to start reading the responses we
> give you.


I do...


> > For example at int array[0][0], array behaves like a **
> > pointer to array[0] which in turn behaves like a pointer to
array[0][0].
>
> First part *right* (or nearly), second part *wrong*.

So now you say the first part is right, and previously you said it is
wrong.
For the second i just checked and it seems wrong (different sizeof
results between &array[0][0] and array[0]), so i assume array[0] behaves
like and int (*)[COLUMNS] pointer. Yet, i am still investigating it.

> > The only misconception i had is that we could use an ** with
> > 2-dimension subscript operators when we asigned to it the address
> > "stored" in array (of array[0][0]).
>
> No, you are clearly still loaded with misconceptions. I'm not trying
> to insult you, or brush you off - it really is my desire to help
> people learn on this group; but I can't waste my time on people who

I understand you want to help and i am grateful for this.


> don't read what a score of regulars have spent their valuable time
> writing for them.

I do read.


> (Guess I shoulda plonked a while ago, but I'm still nervous he's gonna
> give some bizarre advice to a newbie that'll believe him. I'll leave
> that up to RH, LK and CT, who habitually sacrifice themselves for this
> greater good ;) - I don't have time)


Ok, it's your choice.

Ioannis Vranos

unread,
Dec 12, 2001, 4:10:11 PM12/12/01
to
For the following code:


#include <stdio.h>


int main(void)
{
int array[10][10];


printf("%p\n", array[0]);
printf("%p\n", &array[0][0]);

printf("\n%u\n", (unsigned)sizeof(array));
printf("%u\n", (unsigned)sizeof(array[0]));

return 0;
}


my system produces the following results:

C:\c>temp
0012FDFC
0012FDFC

400
40


It is apparent that arrray[0] is some kind of pointer, the last 2
results look bizarre to me. Any ideas?

Tobias Oed

unread,
Dec 12, 2001, 4:27:14 PM12/12/01
to
Ioannis Vranos wrote:
>
> "Micah Cowan" <mi...@cowanbox.com> wrote in message
> news:yu8pu5k...@mcowan-linux.transmeta.com...
> > >
> > > The difference between arrays and pointers. An array behaves like a
> > > pointer to the first element which can't point somewhere else. A
> > > multidimensional array behaves like a ** pointer which can't point
> > > somewhere else.
> >
> > You just proved my point again. As several people, including myself,
> > have already pointed out, a multidimensional array has *NOTHING AT
> > ALL* to do with double pointers. I've had it. I'm not reading any of
>
> We have the code:
>
> #include <stdio.h>
>
> int main(void)
> {
> int array[10][10];
> int *p=array;
>
> return 0;
> }
>
> Results from BCC32:
>
> Warning W8075 temp.c 7: Suspicious pointer conversion in function main
>
> That means that "array" doesn't behave as an int *. So explain me please
> like what pointer type array behaves.

it behaves like a pointer to an array of 10 ints. Try

int (*p)[10]=array;

in your code. That compiles just fine.

Tobias Oed

unread,
Dec 12, 2001, 4:32:12 PM12/12/01
to
Ioannis Vranos wrote:
>
> For the following code:
>
> #include <stdio.h>
>
> int main(void)
> {
> int array[10][10];
>
> printf("%p\n", array[0]);
> printf("%p\n", &array[0][0]);
>
> printf("\n%u\n", (unsigned)sizeof(array));
> printf("%u\n", (unsigned)sizeof(array[0]));
>
> return 0;
> }
>
> my system produces the following results:
>
> C:\c>temp
> 0012FDFC
> 0012FDFC
>
> 400
> 40
>

What's the trouble? array is an array of 10 arrays of 10 ints. So
sizeof array=10*sizeof *array=10*(10*sizeof(int))=400 with
sizeof int==4. array[0] is an array of 10 ints so
sizeof array[0]=10 sizeof(int)=40.

Tobias.

Ioannis Vranos

unread,
Dec 12, 2001, 4:31:43 PM12/12/01
to
"Tobias Oed" <tob...@physics.odu.edu> wrote in message
news:3C17CCDC...@physics.odu.edu...

>
> What's the trouble? array is an array of 10 arrays of 10 ints. So
> sizeof array=10*sizeof *array=10*(10*sizeof(int))=400 with
> sizeof int==4. array[0] is an array of 10 ints so
> sizeof array[0]=10 sizeof(int)=40.

Yes you are right, the correct question should be "what kind of pointer
array[0] behaves like?". If you answered me to this one i would be
grateful. :)

Ioannis Vranos

unread,
Dec 12, 2001, 4:37:28 PM12/12/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message
news:10081926...@athprx02.forthnet.gr...

>
> Yes you are right, the correct question should be "what kind of
pointer
> array[0] behaves like?". If you answered me to this one i would be
> grateful. :)

I have discovered that the assignment in the code:

#include <stdio.h>

int main(void)
{
int array[10][10];

int *p[10];

*p=array[0];

printf("%u %u\n", (unsigned)sizeof(*p), (unsigned)sizeof(array[0]));

return 0;
}


doesn't produce any "suspicious conversion" warning messages, although
their size differs. So probably array[0] behaves like the *p pointer
type in the code. So an answer to the question "like what pointer type
array[0] behaves" or " what type is *p" would be great to me.

*p is not int type, sizeof(**p)==sizeof(int).

Tobias Oed

unread,
Dec 12, 2001, 4:48:35 PM12/12/01
to
Ioannis Vranos wrote:
>
> "Tobias Oed" <tob...@physics.odu.edu> wrote in message
> news:3C17CCDC...@physics.odu.edu...
> >
> > What's the trouble? array is an array of 10 arrays of 10 ints. So
> > sizeof array=10*sizeof *array=10*(10*sizeof(int))=400 with
> > sizeof int==4. array[0] is an array of 10 ints so
> > sizeof array[0]=10 sizeof(int)=40.
>
> Yes you are right, the correct question should be "what kind of pointer
> array[0] behaves like?". If you answered me to this one i would be
> grateful. :)

Acording to the Rule, in a value context an array decays to a pointer
to the first element. array is an array of 10 arrays of 10 ints. The
first element is therefor an array of 10 ints. Therefor, array decays
to pointer to an array of 10 ints in a value context. Looking at the
answer I made in another post,
int (*p)[10]=array[0];
is an illustration of that.
Tobias.

Ioannis Vranos

unread,
Dec 12, 2001, 4:42:39 PM12/12/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message
news:10081930...@athprx02.forthnet.gr...

> int *p[10];
>
> *p=array[0];

! this is an error sorry.

Ioannis Vranos

unread,
Dec 12, 2001, 4:48:37 PM12/12/01
to
"Tobias Oed" <tob...@physics.odu.edu> wrote in message
news:3C17D0B3...@physics.odu.edu...

>
> Acording to the Rule, in a value context an array decays to a pointer
> to the first element. array is an array of 10 arrays of 10 ints. The
> first element is therefor an array of 10 ints. Therefor, array decays
> to pointer to an array of 10 ints in a value context. Looking at the
> answer I made in another post,
> int (*p)[10]=array[0];
> is an illustration of that.
> Tobias.

No, you are wrong on this one...

The code:

#include <stdio.h>

int main(void)
{
int array[10][10];

int (*p)[10]=array[0];

return 0;
}

produces:

Warning W8075 temp.c 6: Suspicious pointer conversion in function main


So the assignment operands are not of the same type. However the code:

#include <stdio.h>

int main(void)
{
int array[10][10];

int (*p)[10]=array;

return 0;
}

compiles without warnings so they are of the same type (we can use p in
the p[i][j] subscript notation).


Also the code:


#include <stdio.h>

int main(void)
{
int array[10][10];

int *p=array[0];


return 0;
}

produces no warnings too, so array[0] behaves probably as int *, the
thing that i mentioned first place and got complained and plonked by
Micah.

Ioannis Vranos

unread,
Dec 12, 2001, 4:57:40 PM12/12/01
to
So to summarize what i have understood so far:

A) In the case of int ar[20][10];


ar behaves like an int (*)[10] which is something like a specialised int
** pointer, it knows the length of each row so we can use the subscript
notation:

int (*p)[10]=ar;

p[0][3]=7;


i) I said "something like a specialised int ** pointer"because we can
use both in the p[i][j] notation.


B) ar[0] behaves like int * (or as the name of a 1-dimensional int array
since it is one).

Barry Schwarz

unread,
Dec 12, 2001, 7:33:49 PM12/12/01
to
On Wed, 12 Dec 2001 23:37:28 +0200, "Ioannis Vranos"
<noicys@no_spam.yahoo.com> wrote:

>"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message
>news:10081926...@athprx02.forthnet.gr...
>>
>> Yes you are right, the correct question should be "what kind of
>pointer
>> array[0] behaves like?". If you answered me to this one i would be
>> grateful. :)
>
>I have discovered that the assignment in the code:
>
>#include <stdio.h>
>
>int main(void)
>{
> int array[10][10];
> int *p[10];
>
> *p=array[0];
>
> printf("%u %u\n", (unsigned)sizeof(*p), (unsigned)sizeof(array[0]));
>
> return 0;
>}
>
>
>doesn't produce any "suspicious conversion" warning messages, although
>their size differs. So probably array[0] behaves like the *p pointer
>type in the code. So an answer to the question "like what pointer type
>array[0] behaves" or " what type is *p" would be great to me.
>
>*p is not int type, sizeof(**p)==sizeof(int).
>

You are just going to beat this to death, aren't you.

Under certain conditions, an unsubscripted array name will "decay" to
address of the first element of the array. array[0] is such an
unsubscripted array name. (Note that array is an array of 10 array of
10 int. Therefore, array[0] is the first array of 10 int in the
larger array.) This is one of the condition where the decay occurs.
Therefore, array[0] is treated as &array[0][0] which has type pointer
to int. *p is the same as p[0] and is simply the first pointer in the
array of pointers. This pointer also has type pointer to int. The
assignment is therefore completely acceptable.

While true, you last sentence is irrelevant. sizeof *p == sizeof
(int*) is the relevant equality.

And the answer to your question is that array[0] does not behave like
any type of pointer. But under certain conditions, when an
unsubscripted array name appears in the source, it will be treated in
the executable as the address of the first element of the array.

Barry Schwarz

unread,
Dec 12, 2001, 7:33:50 PM12/12/01
to
On Wed, 12 Dec 2001 23:57:40 +0200, "Ioannis Vranos"
<noicys@no_spam.yahoo.com> wrote:

>So to summarize what i have understood so far:
>
>A) In the case of int ar[20][10];
>
>
>ar behaves like an int (*)[10] which is something like a specialised int
>** pointer, it knows the length of each row so we can use the subscript
>notation:
>
>int (*p)[10]=ar;
>
>p[0][3]=7;
>
>
> i) I said "something like a specialised int ** pointer"because we can
>use both in the p[i][j] notation.

And as soon you stop saying it we will stop telling you it is wrong.


>
>
>B) ar[0] behaves like int * (or as the name of a 1-dimensional int array
>since it is one).
>

The remainder of you conclusions are subject to certain limitations.
For example, ar and p behave nothing alike when they are the operand
of the sizeof operator. sizeof p will be something like 4 or 8.
sizeof ar will be 200*sizeof(int), something on the order of 400 to
1600.

Barry Schwarz

unread,
Dec 12, 2001, 7:33:48 PM12/12/01
to
On Wed, 12 Dec 2001 23:31:43 +0200, "Ioannis Vranos"
<noicys@no_spam.yahoo.com> wrote:

>"Tobias Oed" <tob...@physics.odu.edu> wrote in message
>news:3C17CCDC...@physics.odu.edu...
>>
>> What's the trouble? array is an array of 10 arrays of 10 ints. So
>> sizeof array=10*sizeof *array=10*(10*sizeof(int))=400 with
>> sizeof int==4. array[0] is an array of 10 ints so
>> sizeof array[0]=10 sizeof(int)=40.
>
>Yes you are right, the correct question should be "what kind of pointer
>array[0] behaves like?". If you answered me to this one i would be
>grateful. :)

array[0] doesn't behave like any pointer; it behaves like an array of
10 int.

Ioannis Vranos

unread,
Dec 12, 2001, 7:59:28 PM12/12/01
to
"Barry Schwarz" <schw...@deloz.net> wrote in message
news:9v8t1c$s9s$1...@216.39.135.152...

> array[0] doesn't behave like any pointer; it behaves like an array of
> 10 int.

Which array name behaves like a pointer to pointer assignments. In a few
words we can assign array[0] to an int *. I am not telling it is a
pointer 9of course), i am looking for the kind of pointer to assign it
to. And array[0] behaves like an int * pointer (which of course can't
point somewhere else, e.t.c. e.t.c.).

Ioannis Vranos

unread,
Dec 12, 2001, 7:56:40 PM12/12/01
to
"Barry Schwarz" <schw...@deloz.net> wrote in message
news:9v8t1e$s9s$3...@216.39.135.152...


Well as we know the name of an array behaves like a pointer but when we
use the sizeof operator on its name the result is the total bytes of its
elements.

Chris Torek

unread,
Dec 12, 2001, 11:42:12 PM12/12/01
to
In an article that was not copied to the newsguy.com servers:

>On Wed, 12 Dec 2001 23:57:40 +0200, "Ioannis Vranos"
><noicys@no_spam.yahoo.com> wrote:
>>So to summarize what i have understood so far:

[various misunderstandings snipped]

In article <9v8t1e$s9s$3...@216.39.135.152>


Barry Schwarz <schw...@deloz.net> wrote:
>The remainder of you conclusions are subject to certain limitations.
>For example, ar and p behave nothing alike when they are the operand
>of the sizeof operator. sizeof p will be something like 4 or 8.
>sizeof ar will be 200*sizeof(int), something on the order of 400 to
>1600.

Since I only see snippets of Ioannis Vranos's postings, I cannot
be certain; but it appears to me that he is doing something that
is possible, but fruitless: inventing a complicated system that
can explain everything C does with pointers and arrays, instead of
using a simple system that explains everything C does with pointers
and arrays.

For comparison, consider the ancient Greeks (who, as I once noted,
probably sat around their campfires inventing algorithms and then
going, "Damn! If only we had some computers!" :-) ). They observed
the "motion of the stars in the heavens" and came up with ways to
explain them. The big problem was the planets, which normally mostly
moved in the same directions as the stars, but at different speeds,
and then occasionally turned around and made "retrograde" motions.

If one begins by assuming that the Earth is the center of a rotary
system, one can explain the motion of not only the sun and stars,
but also the planets, by building a complicated system of "epicycles"
-- wheels within wheels, as it were. Each star is attached to a
device that moves it around the earth at a uniform speed, but the
planets are attached to devices that move on devices that move on
devices, that eventually give you circles moving at constant speeds.

Within the limitations of "unaided eye" observation over the course
of a single lifetime, this horribly complicated explanation for
the motion of the heavens actually *works*. It is very difficult
to work with, but it allows you to predict where and when each
planet will appear in the sky.

On the other hand, if we throw away the assumption that the earth
is the center of this system, and instead assume that the *sun* is
the center, with all the planets revolving in circles (or, for more
precision, ellipses, although this is not needed for naked-eye
observations) around the sun -- and the moon revolving in turn
around the earth -- then we end up with a remarkably simple system
that *also* explains everything and allows you to make the exact
same predictions. Instead of dealing with hundreds of separate
epicycles with weird linkages, the new system has a simple, trivially
memorized rule-set: "Sun at center, stars fixed, planets move around
sun, moon moves around Earth; orbital rates all determined by
distance."

If Mr Vranos would simply give up the unreasonable "epicycle
assumption" -- that arrays and pointers are somehow equivalent, rather
than that array objects become pointer values by following one
simple, fundamental rule; "The Rule", as I call it -- why then,
all the complications of his system would go away.

In one sense, it does not matter whether you use a simple "The
Rule" system, or some horribly complicated "epicycle-like" system
that gives the same answers at horrendous mental cost. In another,
of course, it does. Memorizing and using the simple system is
easy, and using it correctly gives you the right answer, so you
will usually come up with the right answer. Memorizing and using
the complicated system is hard, and *only* using it correctly gives
you the right answer, so you will often come up with the wrong one.

And on another note, I cannot resist quoting something from my web
page, especially with 17 December arriving soon:

One Rule to ring them all
One Rule to find them
One Rule to point them all
And in the language bind them
-- with apologies to J.R.R.Tolkien
--
In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.eng.bsdi.com/torek/ (not always up) I report spam to abuse@.
"nos...@elf.eng.bsdi.com" *is* my address (one of many actually).

Ioannis Vranos

unread,
Dec 13, 2001, 5:24:15 AM12/13/01
to
"Chris Torek" <nos...@elf.eng.bsdi.com> wrote in message
news:9v9bj4$bp$1...@elf.eng.bsdi.com...

>
> Since I only see snippets of Ioannis Vranos's postings, I cannot
> be certain; but it appears to me that he is doing something that
> is possible, but fruitless: inventing a complicated system that
> can explain everything C does with pointers and arrays, instead of
> using a simple system that explains everything C does with pointers
> and arrays.

Basically i am trying to see things in a united theory view. :) That
multidimensional arrays have in reality only one dimension, e.t.c.. :)


> For comparison, consider the ancient Greeks (who, as I once noted,

Ohh, now you enter in very sensitive waters.


> probably sat around their campfires inventing algorithms and then
> going, "Damn! If only we had some computers!" :-) ). They observed


They had not campfires, but buildings. :)


Yes, and while trying to not offend and upset anyone in here, the same
time (around 1000 BC) other people of other nations were hunting down
flies and sleeping in caves. :)


>
> If Mr Vranos would simply give up the unreasonable "epicycle
> assumption" -- that arrays and pointers are somehow equivalent, rather

I did not say they are equivalent, i was checking the limits of the
pointer system while exploring "what pointer type" each array type is
behaving like. Anyway this quest has ended as i have reached certain
conclusions.

> than that array objects become pointer values by following one
> simple, fundamental rule; "The Rule", as I call it -- why then,
> all the complications of his system would go away.


You mean it returns a pointer to the first element. Probably you had not
understood the dual purpose of my effort.


> In one sense, it does not matter whether you use a simple "The
> Rule" system, or some horribly complicated "epicycle-like" system
> that gives the same answers at horrendous mental cost. In another,
> of course, it does. Memorizing and using the simple system is
> easy, and using it correctly gives you the right answer, so you
> will usually come up with the right answer. Memorizing and using
> the complicated system is hard, and *only* using it correctly gives
> you the right answer, so you will often come up with the wrong one.
>
> And on another note, I cannot resist quoting something from my web
> page, especially with 17 December arriving soon:
>
> One Rule to ring them all
> One Rule to find them
> One Rule to point them all
> And in the language bind them
> -- with apologies to J.R.R.Tolkien


"Do you believe in the existence of extraterrestrials?" Fox Molder.

Ioannis Vranos

unread,
Dec 13, 2001, 5:40:28 AM12/13/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message
news:10082390...@athprx02.forthnet.gr...

> > than that array objects become pointer values by following one
> > simple, fundamental rule; "The Rule", as I call it -- why then,
> > all the complications of his system would go away.
>
>
> You mean it returns a pointer to the first element. Probably you had
not
> understood the dual purpose of my effort.

To understand an example. int array[20][10]; . I was trying to find at
what pointer type we can assign array[0] (it's an array and the name
returns an address) without having warnings about type mismatch. The
correct type is int *. With your rule of first element since array[0]
behaves like an int *, array should behave like an int ** (it's what i
said the first time). But the correct type is not int ** but something
in the middle: int (*)[10]. I was following your rule first place, but
when i found that it is not so accurate i began exploring things till
the end. :)

Tobias Oed

unread,
Dec 13, 2001, 10:34:57 AM12/13/01
to
Ioannis Vranos wrote:

> > int (*p)[10]=array[0];
> > is an illustration of that.
> > Tobias.
>
> No, you are wrong on this one...
>

> int main(void)
> {
> int array[10][10];
> int (*p)[10]=array[0];
>
> return 0;
> }
>
> produces:
>
> Warning W8075 temp.c 6: Suspicious pointer conversion in function main
>
> So the assignment operands are not of the same type. However the code:
>

> int main(void)
> {
> int array[10][10];
> int (*p)[10]=array;
>
> return 0;
> }
>

I fail to see the difference between these two codes and still
claim to be right.
Vranos, I'm afraid your send button's trigger threshold is too
low, you need to take it to a dealer to get a tuned up :)
Tobias.

Ioannis Vranos

unread,
Dec 13, 2001, 11:09:52 AM12/13/01
to
"Tobias Oed" <tob...@physics.odu.edu> wrote in message
news:3C18CAA1...@physics.odu.edu...

> Ioannis Vranos wrote:
> >
> > No, you are wrong on this one...
> >
> > int main(void)
> > {
> > int array[10][10];
> > int (*p)[10]=array[0];
> >
> > return 0;
> > }
> >
> > produces:
> >
> > Warning W8075 temp.c 6: Suspicious pointer conversion in function
main
> >
> > So the assignment operands are not of the same type. However the
code:
> >
> > int main(void)
> > {
> > int array[10][10];
> > int (*p)[10]=array;
> >
> > return 0;
> > }
> >
>
> I fail to see the difference between these two codes and still
> claim to be right.
> Vranos, I'm afraid your send button's trigger threshold is too
> low, you need to take it to a dealer to get a tuned up :)
> Tobias.


Uff, although i have finished with that topic, here we go again. :)
array[0] and array are 2 different types. array[0] is a simple array of
10 integers while array is an array of 10 arrays of 10 integers.

Ioannis Vranos

unread,
Dec 13, 2001, 11:12:52 AM12/13/01
to
"Tobias Oed" <tob...@physics.odu.edu> wrote in message
news:3C18CAA1...@physics.odu.edu...


Also the first would be valid if it had the address of operator in front
of arrray[0]. That is:

int main(void)
{
int array[10][10];

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

return 0;

Richard Heathfield

unread,
Dec 13, 2001, 2:30:32 PM12/13/01
to
Ioannis Vranos wrote:
>
> For the following code:
>
> #include <stdio.h>
>
> int main(void)
> {
> int array[10][10];
>
> printf("%p\n", array[0]);

Undefined behaviour.

> printf("%p\n", &array[0][0]);

Undefined behaviour.

>
> printf("\n%u\n", (unsigned)sizeof(array));
> printf("%u\n", (unsigned)sizeof(array[0]));
>
> return 0;
> }
>
> my system produces the following results:
>
> C:\c>temp
> 0012FDFC
> 0012FDFC
>
> 400

10 * 10 * sizeof(int) - so on your system, ints are 4 bytes.

> 40

10 * sizeof(int).

>
> It is apparent that arrray[0] is some kind of pointer,

Not at all. It's an array.

> the last 2
> results look bizarre to me.

They look right to me.


> Any ideas?

What were you expecting?

--
Richard Heathfield : bin...@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton


Ioannis Vranos

unread,
Dec 13, 2001, 5:50:19 PM12/13/01
to
"Richard Heathfield" <bin...@eton.powernet.co.uk> wrote in message
news:3C1901D8...@eton.powernet.co.uk...

> > printf("%p\n", array[0]);
>
> Undefined behaviour.
>
> > printf("%p\n", &array[0][0]);
>
> Undefined behaviour.


What is the proper way to print their address.


> > my system produces the following results:
> >
> > C:\c>temp
> > 0012FDFC
> > 0012FDFC
> >
> > 400
>
> 10 * 10 * sizeof(int) - so on your system, ints are 4 bytes.
>
> > 40
>
> 10 * sizeof(int).


Yes i know that.

> > It is apparent that arrray[0] is some kind of pointer,
>
> Not at all. It's an array.


What i meant is that it is an array with a result its name to behave
like a pointer. But we must always be accurate on what we say so i
accept this critic. :)


> > the last 2
> > results look bizarre to me.
>
> They look right to me.

Yeah, i had stuck to something but after later messages i have
understood anything in detail completely. :) Which i am 100% sure will
force you write something like "i do not think so". :)


> > Any ideas?
>
> What were you expecting?

I was confused in that time since array[0] is an array and the array
containing that array isn't a ** pointer (since the "Rule" as one
mentioned is that the name of an array is an address to its first
element). Anyway anything was cleared now.

Barry Schwarz

unread,
Dec 13, 2001, 8:53:33 PM12/13/01
to
On Fri, 14 Dec 2001 00:50:19 +0200, "Ioannis Vranos"
<noicys@no_spam.yahoo.com> wrote:

>"Richard Heathfield" <bin...@eton.powernet.co.uk> wrote in message
>news:3C1901D8...@eton.powernet.co.uk...
>> > printf("%p\n", array[0]);
>>
>> Undefined behaviour.
>>
>> > printf("%p\n", &array[0][0]);
>>
>> Undefined behaviour.
>
>
>What is the proper way to print their address.

They must be cast to void*.

Ioannis Vranos

unread,
Dec 13, 2001, 9:45:49 PM12/13/01
to
"Barry Schwarz" <schw...@deloz.net> wrote in message
news:9vbm2t$8g8$0...@216.39.134.228...

> >What is the proper way to print their address.
>
> They must be cast to void*.

Ok, thanks.

Richard Bos

unread,
Dec 14, 2001, 3:03:53 AM12/14/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote:

> "Richard Heathfield" <bin...@eton.powernet.co.uk> wrote in message
> news:3C1901D8...@eton.powernet.co.uk...

> > > my system produces the following results:
> > >
> > > C:\c>temp
> > > 0012FDFC
> > > 0012FDFC
> > >
> > > 400
> >
> > 10 * 10 * sizeof(int) - so on your system, ints are 4 bytes.
> >
> > > 40
> >
> > 10 * sizeof(int).
>
> Yes i know that.
>
> > > It is apparent that arrray[0] is some kind of pointer,
> >
> > Not at all. It's an array.
>
> What i meant is that it is an array with a result its name to behave
> like a pointer.

No, that is _not_ the result. An array decays to a pointer _under some
circumstances_. Actually, under most circumstances, which is probably
why so many people are, like you, confused by the difference between
pointers and arrays.
However, the important thing here is that using an array as the operand
of sizeof is one of the circumstances in which it does _not_ decay to a
pointer. Therefore, you are seeing the sizes of the arrays, not the
sizes of the pointers to their first elements.
BTW, the other situations when an array doesn't decay are when its
address is taken using &, and when it is a string literal used to
initialise a char array.

Richard

Ioannis Vranos

unread,
Dec 14, 2001, 6:52:56 AM12/14/01
to
"Richard Bos" <in...@hoekstra-uitgeverij.nl> wrote in message
news:3c19b099....@news.tiscali.nl...

> > What i meant is that it is an array with a result its name to behave
> > like a pointer.
>
> No, that is _not_ the result. An array decays to a pointer _under some
> circumstances_. Actually, under most circumstances, which is probably
> why so many people are, like you, confused by the difference between
> pointers and arrays.

I am not confuse arrays and pointers. I was bored to refer the phrase
"under some circumstances", especially to mention them explicitly
(dereference using *, reading using the subscript notation (which we
could start a new discussion on that pointers borrowed that notation
from arrays), e.t.c.. Spare me. :)


> However, the important thing here is that using an array as the
operand
> of sizeof is one of the circumstances in which it does _not_ decay to
a
> pointer. Therefore, you are seeing the sizes of the arrays, not the

Yes, it gives us the size in bytes of all elements.


> sizes of the pointers to their first elements.
> BTW, the other situations when an array doesn't decay are when its
> address is taken using &, and when it is a string literal used to
> initialise a char array.

Yes.

Micah Cowan

unread,
Dec 14, 2001, 4:40:22 PM12/14/01
to
"Ioannis Vranos" <noicys@no_spam.yahoo.com> writes:

> "Richard Bos" <in...@hoekstra-uitgeverij.nl> wrote in message
> news:3c19b099....@news.tiscali.nl...
> > > What i meant is that it is an array with a result its name to behave
> > > like a pointer.
> >
> > No, that is _not_ the result. An array decays to a pointer _under some
> > circumstances_. Actually, under most circumstances, which is probably
> > why so many people are, like you, confused by the difference between
> > pointers and arrays.
>
> I am not confuse arrays and pointers.

You keep telling yourself that.


Micah (only saw this message because his own post is in the
references, boosting the score)

Ioannis Vranos

unread,
Dec 14, 2001, 5:13:11 PM12/14/01
to
"Micah Cowan" <mi...@cowanbox.com> wrote in message
news:yu87krp...@mcowan-linux.transmeta.com...

>
> You keep telling yourself that.

Ok how many times? I start with 10:


I do not confuse arrays and pointers.
I do not confuse arrays and pointers.
I do not confuse arrays and pointers.
I do not confuse arrays and pointers.
I do not confuse arrays and pointers.
I do not confuse arrays and pointers.
I do not confuse arrays and pointers.
I do not confuse arrays and pointers.
I do not confuse arrays and pointers.
I do not confuse arrays and pointers.

willem veenhoven

unread,
Dec 14, 2001, 5:35:27 PM12/14/01
to
Ioannis Vranos wrote:

>
> Micah Cowan wrote:
>
> > You keep telling yourself that.
>
> Ok how many times? I start with 10:
>
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.
> I do not confuse arrays and pointers.

Yes, you do
Yes, you do
Yes, you do
Yes, you do
Yes, you do
Yes, you do
Yes, you do
Yes, you do
Yes, you do
Yes, you do
Yes, you do

I added one to compensate for your future mistakes :)

willem

Ioannis Vranos

unread,
Dec 14, 2001, 6:09:01 PM12/14/01
to
"willem veenhoven" <wil...@veenhoven.com> wrote in message
news:3C1A7EAF...@veenhoven.com...

>
> Yes, you do
> Yes, you do
> Yes, you do
> Yes, you do
> Yes, you do
> Yes, you do
> Yes, you do
> Yes, you do
> Yes, you do
> Yes, you do
> Yes, you do
>
> I added one to compensate for your future mistakes :)

:)

Lawrence Kirby

unread,
Dec 13, 2001, 10:30:19 AM12/13/01
to
In article <10081942...@athprx02.forthnet.gr>
noicys@no_spam.yahoo.com "Ioannis Vranos" writes:

>So to summarize what i have understood so far:
>
>A) In the case of int ar[20][10];
>
>
>ar behaves like an int (*)[10]

It is converted to a value that is a pointer to it's first element
(and is therefore of type int (*)[10]) in most expression contexts.
ar is still fundamentally an array however, e.g. it provides space
for 20 arrays of 10 ints and ultimately 200 ints. A pointer by itself
doesn't do that and also ar doesn't create any pointer *objects*.

>which is something like a specialised int
>** pointer,

No, it isn't. Much of the discussion was about the *difference* between
int ** and (say) int (*)[10]. When you go likening them to each other
again I wonder if the previous discussion has had any impact.

>it knows the length of each row so we can use the subscript
>notation:
>
>int (*p)[10]=ar;
>
>p[0][3]=7;

That's fine. The value of p is in the same as the value of
ar and the same things can be done with them. Not all contexts use
value: sizeof p and sizeof are are different (unless you have very
weird large pointers) and &p and &ar are different: &p has type
int (**)[10] and &ar has type int (*)[20][10]. When you look at the
object itself or its type then the difference between ar and p
become apparent even though they have the same "value".

> i) I said "something like a specialised int ** pointer"because we can
>use both in the p[i][j] notation.

True, but that ignores the vital fact that int **q; requires you to set
up a completely different form of datastructure before q[i][j] will work.
The fact that when p and q are set up correctly you can use then in
expressions with the same syntax doesn't change the fact that what they
are doing is different. Given integers i and j then i+j and p+j have the
same syntax but there are significant differences in what they do; don't
be sidelined by syntactic similarities.

>B) ar[0] behaves like int * (or as the name of a 1-dimensional int array
>since it is one).

ar[0] behaves like an array of 10 ints, that is the type of object it is.
Like any array if you take its value you get a pointers to its first
element. This is just a value in the same way that given int i; then &i
results in a value that is a pointer to i. In neither case do any actual
int * objects exist.

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------

Lawrence Kirby

unread,
Dec 13, 2001, 10:57:50 AM12/13/01
to
In article <10082399...@athprx02.forthnet.gr>
noicys@no_spam.yahoo.com "Ioannis Vranos" writes:

>"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message
>news:10082390...@athprx02.forthnet.gr...
>> > than that array objects become pointer values by following one
>> > simple, fundamental rule; "The Rule", as I call it -- why then,
>> > all the complications of his system would go away.
>>
>>
>> You mean it returns a pointer to the first element. Probably you had
>not
>> understood the dual purpose of my effort.
>
>To understand an example. int array[20][10]; . I was trying to find at
>what pointer type we can assign array[0] (it's an array and the name
>returns an address) without having warnings about type mismatch.

Consider why those warnings are there. They aren't there just to make
life difficult for C programmers (after all it was C programmers who
formulated the rules), they are there to prevent real mistakes and
flawed logic.

>The
>correct type is int *. With your rule of first element since array[0]
>behaves like an int *, array should behave like an int ** (it's what i
>said the first time).

No, array[0] has type int [10] and behaves like any int [10] array. You
can derive a pointer of type int * that can be used to access the elements
of the array. C happens to provide a syntactic shortcut to do this in
many contexts by just specifying the array lvalue, but that doesn't
change what array[0] actually is (an array of 10 ints). Similarly given
int i; I can create a pointer to i using &i. That doesn't make i itself
a pointer.

>But the correct type is not int ** but something
>in the middle: int (*)[10]. I was following your rule first place, but
>when i found that it is not so accurate i began exploring things till
>the end. :)

The rule is that you need a pointer to the element type, not a pointer
to some other type derived from the element type. Given

int i = -1;
unsigned long ul = 0;

what is type type of i in

printf("%lu\n", i + ul);

? Note that when both of the operands of + have arithmetic (integer or
floating point) type then they must have the same type before the addition
can be performed.

Chris Torek

unread,
Dec 17, 2001, 5:25:04 AM12/17/01
to
Again, Ioannis Vranos's postings never make it here, but
article <100825...@genesis.demon.co.uk> by
Lawrence Kirby <fr...@genesis.demon.co.uk> quotes him:

>In article <10082399...@athprx02.forthnet.gr>
> noicys@no_spam.yahoo.com "Ioannis Vranos" writes:
>>"Ioannis Vranos" <noicys@no_spam.yahoo.com> wrote in message
>>news:10082390...@athprx02.forthnet.gr...

>>To understand an example. int array[20][10]; . I was trying to find at
>>what pointer type we can assign array[0] (it's an array and the name
>>returns an address) without having warnings about type mismatch.

[snippage of stuff from LK]

>>The correct type is int *. With your rule of first element since array[0]
>>behaves like an int *, array should behave like an int ** (it's what i
>>said the first time).

LK correctly notes that:


>No, array[0] has type int [10] and behaves like any int [10] array. You
>can derive a pointer of type int * that can be used to access the elements
>of the array. C happens to provide a syntactic shortcut to do this in
>many contexts by just specifying the array lvalue, but that doesn't
>change what array[0] actually is (an array of 10 ints). Similarly given
>int i; I can create a pointer to i using &i. That doesn't make i itself
>a pointer.

>>But the correct type is not int ** but something
>>in the middle: int (*)[10]. I was following your rule first place, but
>>when i found that it is not so accurate i began exploring things till
>>the end. :)

Before you can apply The Rule, you first need to understand something
even more fundamental.

Consider the following (no arrays at all involved):

void f(void) {
/* initialized just so they have known initial values */
int v = 0, w = 0;

v = 3;
w = v;
/* more code here */
}

There are two ordinary (non-initializer) assignments here, "v = 3"
and "w = v". These set v to 3, and w to 3 as well. But -- how?
More specifically, in the second line, how can it be that we fetch
the *value* of v and assign it into the *object* w? Why did we not
fetch the values of *both* v *and* w and try to set 0 = 3?

One possible answer, of course, is "because the language says so",
but this is not very satisfying. Another is "because it would make
no sense", which I think is more satisfying. It "makes sense"
to distinguish between "places that need an object", like the left
hand side of an "=" operator, and "places that need a value",
like the right hand side of that same operator.

(As an aside, I should point out that there *are* languages that
do not make this kind of distinction. The name of a variable
*always* produces a reference to the object, and if you want the
value, you must explicitly ask for it. To set w to the same value
that is in v, instead of "w = v" you write something more like "w
v @ !": push address of w, push address of v, fetch value at address
on top of stack, and store value on top of stack into address under
that value. Or "w = .v": get address of w, get address of v,
use . operator to find value at address of v, set address on left to
value on right. Doing "w = v" would, in this language, do what C
expresses as "w = (int)&v;".)

Anyway, so, C has "places that need an object", and "places that
need a value". The C90 standard uses terms like "lvalue", but I
prefer to describe these by the simpler names, "object context"
and "value context". C is not at all unusual in this respect;
Fortran, Pascal, and even BASIC and JavaScript and the like all
use similar if not identical concepts. What is unusual about C is
that it has many different "object contexts", such as the operand
of a "++" operator, a "sizeof", or the unary "&" operator. In
other languages, "object context" is largely confined to the left
hand side of an "=" assignment operator.

You need these concepts -- object vs value contexts -- just to
explain simple assignment expressions like "w = v", as well as to
explain why "sizeof arr" is different from "sizeof &arr[0]", even
though the value of "arr" is the same as that produced by &arr[0].

That last -- the "value" of an array -- is where The Rule comes in.

The Rule, the one fundamental rule that is at the root of all the
weirdness about pointers and arrays in C, says:

In a value context, an object of type `array N of T' becomes
a value of type `pointer to T', pointing to the first element
of that object, i.e., the one with subscript 0.

Thus, suppose we have the object declared by "int array[20][10];".
This is an "object" (check) of type "array 20 of ..." (check).
So, N=20 and T="array 10 of int".

That means that *in a value context* (and ONLY in such a context),
the name of the array, by itself, denotes instead a pointer of
type "pointer to T" -- pointer to array 10 of int -- pointing to
the first element of the array, &array[0].

If we want to store that value, we should use a pointer of that
type:

int array[20][10];
int (*ptr)[10];

ptr = array;

The left hand side of an "=" operator has object context, so we
find the object "ptr", which has type "pointer to array 10 of int".
The right hand side has value context, so we find the "value" of
the object called "array". This triggers The Rule, because we have
an array object in a value context. The Rule says that the value
produced has type "pointer to array 10 of int" and points to the
element with subscript 0, i.e., &array[0].

The reason this is "*The* Rule", rather than merely "a rule", is
that it turns out to apply to pointer arithmetic, function calls,
the "*" operator, and even the subscripting operators. This one
single special rule, that the "value" of an array object (when one
is placed in a value context) is a pointer to the array's first
element, gives rise to *all* of the peculiar behaviors observed in
C. In particular, it explains why something like:

fgets(buf, sizeof buf, stream);

works. Without it, you might have to write:

fgets(&buf[0], sizeof buf, stream);

It also explains why a function definition like:

void getline(char buf[], size_t size, FILE *fp) {
/* code */
}

really "means":

void getline(char *buf, size_t size, FILE *fp) {
/* code */
}

Parameters are always passed by value, so what looks like an array
object, but is actually a formal parameter, must have been passed
through The Rule and thus have become a pointer to the array's
first element. Thus, The Rule is deeply connected to the "type
rewrite rule" for parameters, and explains why:

void fn(int p[][10]);

is actually the same prototype as:

void fn(int (*p)[10]);

Here p is a stand-in for what will be a formal parameter, and will
therefore have been passed through The Rule; so if p starts out
with type "array ? of array 10 of int", the type-rewrite rule for
formal parameters changes it to "pointer to array 10 of int", as
shown in the second prototype.

Lawrence Kirby

unread,
Dec 17, 2001, 7:23:06 AM12/17/01
to
In article <9vkh60$b45$1...@elf.eng.bsdi.com>
nos...@elf.eng.bsdi.com "Chris Torek" writes:

...

>Anyway, so, C has "places that need an object", and "places that
>need a value". The C90 standard uses terms like "lvalue", but I
>prefer to describe these by the simpler names, "object context"
>and "value context". C is not at all unusual in this respect;
>Fortran, Pascal, and even BASIC and JavaScript and the like all
>use similar if not identical concepts. What is unusual about C is
>that it has many different "object contexts", such as the operand
>of a "++" operator, a "sizeof", or the unary "&" operator. In
>other languages, "object context" is largely confined to the left
>hand side of an "=" assignment operator.

...

Great explanation, I'd just note one thing: the operand of sizeof
is not an "object context" because things like sizeof(1+1) are valid.
It is something different, perhaps call it a "type context" since
all sizeof is interested in is the type of its operand and it derives
a size from that type.

0 new messages