www.HireAmericanCitizens.org
Author Message
www.HireAmericanCitizens.org

www.HireAmericanCitizens.org

New H-1B website.

Tue, 17 Aug 2004 07:54:09 GMT
www.HireAmericanCitizens.org

Wed, 18 Jun 1902 08:00:00 GMT
www.HireAmericanCitizens.org
So, my C class's midterm had a problem that asked us how we would declare a
variable B that was a pointer to an array of pointers to int.  I wrote
int* (*B)[];

Turns out the instructor had intended
int** B;

After thinking about it for a while, I've decided we're both sort of right,
but I thought I'd run my ideas by comp.lang.c to make sure I'm not
completely off base.

I think my answer is the technically correct one, but his reflects a common
(mis?)usage of the English phrase "pointer to an array" to mean a pointer to
the first element.

Simplying the problem slightly, suppose I have an array of int,
int A[3] = {1, 2, 3};

and I decide to make a "pointer to that array".  I can write

int (*B)[] = &A;   /* implicit cast if & is omitted */
int* C = A;        /* implicit cast if & is present */

and now B and C both point to the SAME LOCATION in memory, though they
differ in level of indirection.  That is, B points to the entire array,
while A points to the first element.  Consequently, **B == *A.  Even more
weirdly, notice that (void*) &A == (void*) A.

So only B can really be called a pointer to an array of int.  But I
*believe* (correct me if I'm wrong) that people (even those who know C) will
typically say without hesitation that
int A[3] = {1, 2, 3};
int* C = A;
sets C to point to an array of three integers.  It seems to me, then, that
that description is technically wrong -- C points to the first integer, not
the entire array -- but common enough that the phrase "pointer to an array"
may sometimes be considered an idiom for "pointer to the first element of an
array", and *under that interpretation* the instructor's intended answer is
the correct one.

Thoughts?  Insights?  Is the question really as ambiguous as I think it is?
Or has my judgment been thoroughly addled by sleep deprivation? :)
--Steve

Tue, 17 Aug 2004 13:54:03 GMT
www.HireAmericanCitizens.org

Quote:
> So, my C class's midterm had a problem that asked us how we would declare a
> variable B that was a pointer to an array of pointers to int.  I wrote
>     int* (*B)[];
> Turns out the instructor had intended
>     int** B;

What? B is a pointer to a pointer to int, an array does not figure into
this at all. Either your instructor doesn't know C or you have
misunderstood him.

Quote:
> After thinking about it for a while, I've decided we're both sort of right,
> but I thought I'd run my ideas by comp.lang.c to make sure I'm not
> completely off base.
> I think my answer is the technically correct one, but his reflects a common
> (mis?)usage of the English phrase "pointer to an array" to mean a pointer to
> the first element.

A pointer to an array is a pointer to an array, not a pointer to the
first element. If you have an array "T []", then its first element is a
"T", and is just as good a "T" as any other "T". Therefore a pointer to
the first element is a "pointer to T", not a "pointer to an array of T".

Quote:
> Simplying the problem slightly, suppose I have an array of int,
>     int A[3] = {1, 2, 3};
> and I decide to make a "pointer to that array".  I can write
>     int (*B)[] = &A;   /* implicit cast if & is omitted */
>     int* C = A;        /* implicit cast if & is present */

I don't think you can declare B like that. You must include the array
size. If you say int (*B)[3]=&A then B is a pointer to an array of int,
while C is a pointer to int.
The fact that C and A have the same value when used as rvalues does not
alter either's type. (Can I say either's like that?)

Quote:
> and now B and C both point to the SAME LOCATION in memory, though they
> differ in level of indirection.  That is, B points to the entire array,
> while A points to the first element.  Consequently, **B == *A.  Even more
> weirdly, notice that (void*) &A == (void*) A.

An array doesn't "point" anywhere. An array includes all the values, it
doesn't point at them. But because you're using A as an rvalue, Lawrence
Kirby's THE RULE steps in and makes A act as a pointer instead of an
array. This doesn't mean A *is* a pointer, though.

Quote:
> So only B can really be called a pointer to an array of int.  But I
> *believe* (correct me if I'm wrong) that people (even those who know C) will
> typically say without hesitation that
>     int A[3] = {1, 2, 3};
>     int* C = A;
> sets C to point to an array of three integers.  It seems to me, then, that
> that description is technically wrong -- C points to the first integer, not
> the entire array -- but common enough that the phrase "pointer to an array"
> may sometimes be considered an idiom for "pointer to the first element of an
> array", and *under that interpretation* the instructor's intended answer is
> the correct one.

No, I believe the correct thing to say is "C points to the first element
of the array A". Unlike A, C really *is* a pointer, and points to the
same location where A[0] is stored.

Quote:
> Thoughts?  Insights?  Is the question really as ambiguous as I think it is?
> Or has my judgment been thoroughly addled by sleep deprivation? :)

I think your instructor is too careless with his terminology. The way
he goes on about pointers and arrays is sure to give rise to "Aren't
pointers and arrays the same thing in C?" -type questions.

--

| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste       W++ B OP+                     |
\----------------------------------------- Finland rules! ------------/
"To know me IS to love me."
- JIPsoft

Tue, 17 Aug 2004 14:54:34 GMT
www.HireAmericanCitizens.org

Quote:
> A pointer to an array is a pointer to an array, not a pointer to the
> first element. If you have an array "T []", then its first element is a
> "T", and is just as good a "T" as any other "T". Therefore a pointer to
> the first element is a "pointer to T", not a "pointer to an array of T".

Cool, that's what I figured.

Quote:
> > Simplying the problem slightly, suppose I have an array of int,
> >     int A[3] = {1, 2, 3};

> > and I decide to make a "pointer to that array".  I can write

> >     int (*B)[] = &A;   /* implicit cast if & is omitted */
> >     int* C = A;        /* implicit cast if & is present */

> I don't think you can declare B like that.

I'm almost sure you can.  Certainly it worked in MSVC.  B's declaration
doesn't actually allocate any space for the array, so there's no need for it
to know the size, is there?

Quote:
> If you say int (*B)[3]=&A then B is a pointer to an array of int,
> while C is a pointer to int.
> The fact that C and A have the same value when used as rvalues does not
> alter either's type. (Can I say either's like that?)

Yeah, but what I found funny was that *B and C* could have the same values,
even though they have different levels of indirection.  (And that's without
even applying THE RULE -- they're both pointers, after all.)

Quote:
> An array doesn't "point" anywhere. An array includes all the values, it
> doesn't point at them. But because you're using A as an rvalue, Lawrence
> Kirby's THE RULE steps in and makes A act as a pointer instead of an
> array. This doesn't mean A *is* a pointer, though.

Agreed.

Quote:
> > So only B can really be called a pointer to an array of int.  But I
> > *believe* (correct me if I'm wrong) that people (even those who know C)
will
> > typically say without hesitation that
> >     int A[3] = {1, 2, 3};
> >     int* C = A;
> > sets C to point to an array of three integers.  It seems to me, then,
that
> > that description is technically wrong -- C points to the first integer,
not
> > the entire array -- but common enough that the phrase "pointer to an
array"
> > may sometimes be considered an idiom for "pointer to the first element
of an
> > array", and *under that interpretation* the instructor's intended answer
is
> > the correct one.

> No, I believe the correct thing to say is "C points to the first element
> of the array A". Unlike A, C really *is* a pointer, and points to the
> same location where A[0] is stored.

Here's why I think the way we talk about it is ambiguous: Joe Newbie looks
at his de{*filter*} and says, well, C points to address 0xFF3A8816 (or
whatever).  What's at 0xFF3A8816?  Hey, what do you know, it's an array.
And that's where C points, isn't it?  0xFF3A8816 is the address of the
array, and C is 0xFF3A8816.  So, he thinks, how can I be wrong when I say
that C points to my array?

Of course, I see your point, that C's type is not "pointer to array of int"
but rather "pointer to int".  But I think common sense is on Joe's side, and
that's why the phrase is ambiguous, or at least highly counter-intuitive.

Quote:
> I think your instructor is too careless with his terminology. The way
> he goes on about pointers and arrays is sure to give rise to "Aren't
> pointers and arrays the same thing in C?" -type questions.

Yeah, in fact it has.  :)
--Steve

Tue, 17 Aug 2004 17:34:46 GMT
www.HireAmericanCitizens.org

Quote:

>> A pointer to an array is a pointer to an array, not a pointer to the
>> first element. If you have an array "T []", then its first element is a
>> "T", and is just as good a "T" as any other "T". Therefore a pointer to
>> the first element is a "pointer to T", not a "pointer to an array of T".
> Cool, that's what I figured.
>> > Simplying the problem slightly, suppose I have an array of int,
>> >     int A[3] = {1, 2, 3};

>> > and I decide to make a "pointer to that array".  I can write

>> >     int (*B)[] = &A;   /* implicit cast if & is omitted */
>> >     int* C = A;        /* implicit cast if & is present */

>> I don't think you can declare B like that.
> I'm almost sure you can.  Certainly it worked in MSVC.  B's declaration
> doesn't actually allocate any space for the array, so there's no need for it
> to know the size, is there?

you can declare a pointer to an incomplete type, but even if you can,
you can not indirect through such a pointer. The pointer must be cast to
a pointer to a complete type for any indirection to be possible.

Quote:
>> If you say int (*B)[3]=&A then B is a pointer to an array of int,
>> while C is a pointer to int.
>> The fact that C and A have the same value when used as rvalues does not
>> alter either's type. (Can I say either's like that?)
> Yeah, but what I found funny was that *B and C* could have the same values,
> even though they have different levels of indirection.  (And that's without
> even applying THE RULE -- they're both pointers, after all.)

Value conversions between one pointer type and another pointer type are
either fully valid (for example assigning a concrete pointer to a void
*) or implementation-defined.
Also, notice that in the above declarations of A, B and C, C points to
A[0], while B points to the whole of A. A and A[0] start at the same
address, so pointers to those have the same values. Incrementing those
pointers would yield different values.

- Show quoted text -

Quote:
>> An array doesn't "point" anywhere. An array includes all the values, it
>> doesn't point at them. But because you're using A as an rvalue, Lawrence
>> Kirby's THE RULE steps in and makes A act as a pointer instead of an
>> array. This doesn't mean A *is* a pointer, though.
> Agreed.
>> > So only B can really be called a pointer to an array of int.  But I
>> > *believe* (correct me if I'm wrong) that people (even those who know C)
> will
>> > typically say without hesitation that
>> >     int A[3] = {1, 2, 3};
>> >     int* C = A;
>> > sets C to point to an array of three integers.  It seems to me, then,
> that
>> > that description is technically wrong -- C points to the first integer,
> not
>> > the entire array -- but common enough that the phrase "pointer to an
> array"
>> > may sometimes be considered an idiom for "pointer to the first element
> of an
>> > array", and *under that interpretation* the instructor's intended answer
> is
>> > the correct one.

>> No, I believe the correct thing to say is "C points to the first element
>> of the array A". Unlike A, C really *is* a pointer, and points to the
>> same location where A[0] is stored.
> Here's why I think the way we talk about it is ambiguous: Joe Newbie looks
> at his de{*filter*} and says, well, C points to address 0xFF3A8816 (or
> whatever).  What's at 0xFF3A8816?  Hey, what do you know, it's an array.
> And that's where C points, isn't it?  0xFF3A8816 is the address of the
> array, and C is 0xFF3A8816.  So, he thinks, how can I be wrong when I say
> that C points to my array?

I think an address, by itself, contains no information whatsoever what
is stored there. C's type system is purely compile-time (at least in
C90). No run-time type information is stored whatsoever.
There's nothing stopping 0xFF3A8816 from being both the address of an
array and the address of a scalar, even at the same time. You have
demonstrated such a case yourself.

Quote:
> Of course, I see your point, that C's type is not "pointer to array of int"
> but rather "pointer to int".  But I think common sense is on Joe's side, and
> that's why the phrase is ambiguous, or at least highly counter-intuitive.

I think there's nothing counter-intuitive about it. It is ambiguous,
because C's type system allows you to use the same value as different
types.

Quote:
>> I think your instructor is too careless with his terminology. The way
>> he goes on about pointers and arrays is sure to give rise to "Aren't
>> pointers and arrays the same thing in C?" -type questions.
> Yeah, in fact it has.  :)

--

| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.*-*-*.com/ ~palaste       W++ B OP+                     |
\----------------------------------------- Finland rules! ------------/
"'It can be easily shown that' means 'I saw a proof of this once (which I didn't
understand) which I can no longer remember'."
- A maths teacher

Tue, 17 Aug 2004 18:00:00 GMT
www.HireAmericanCitizens.org

Quote:
> An array doesn't "point" anywhere. An array includes all the values, it
> doesn't point at them. But because you're using A as an rvalue, Lawrence
> Kirby's THE RULE steps in and makes A act as a pointer instead of an
> array. This doesn't mean A *is* a pointer, though.

Lawrence has already corrected you once on this, as have I. It is Chris Torek
who is the proponent of "The Rule", you should properly attribute it.

-Daniel

Wed, 18 Aug 2004 01:34:45 GMT
www.HireAmericanCitizens.org

Quote:

[...]
> > > >     int (*B)[] = &A;   /* implicit cast if & is omitted */

> > > I don't think you can declare B like that.

> > I'm almost sure you can.  Certainly it worked in MSVC.  B's declaration
> > doesn't actually allocate any space for the array, so there's no need
for it
> > to know the size, is there?

> you can declare a pointer to an incomplete type, but even if you can,
> you can not indirect through such a pointer. The pointer must be cast to
> a pointer to a complete type for any indirection to be possible.

So what's the answer to the original question, then?  -- How do you properly
declare B to be a pointer to an array of pointers to int?
--Steve

Wed, 18 Aug 2004 02:03:17 GMT
www.HireAmericanCitizens.org

Quote:

> [...]
> > > > >     int (*B)[] = &A;   /* implicit cast if & is omitted */

> > > > I don't think you can declare B like that.

> > > I'm almost sure you can.
> > > Certainly it worked in MSVC.  B's declaration
> > > doesn't actually allocate any space for the array,
> > > so there's no need for it
> > > to know the size, is there?

> > I'm not sure if
> > you can declare a pointer to an incomplete type,
> > but even if you can,
> > you can not indirect through such a pointer.
> > The pointer must be cast to
> > a pointer to a complete type for any indirection to be possible.

> So what's the answer to the original question, then?
> -- How do you properly
> declare B to be a pointer to an array of pointers to int?

int *array[47] = {0};

int *(*B)[47] = &array;
/* B is a pointer to the array */
B = &array;

int **BB = array;
/* BB is a pointer to the first element of the array */
BB = array;

--
pete

Wed, 18 Aug 2004 03:33:07 GMT
www.HireAmericanCitizens.org

Quote:

> > So what's the answer to the original question, then?
> > -- How do you properly
> > declare B to be a pointer to an array of pointers to int?

> int *array[47] = {0};

> int *(*B)[47] = &array;
> /* B is a pointer to the array */
> B = &array;

More generally, then:

int *(*B)[sizeof array / sizeof *array] = &array;

or

int *(*B)[sizeof array / sizeof *array];
B = &array;

Quote:
> int **BB = array;
> /* BB is a pointer to the first element of the array */
> BB = array;

--
pete

Wed, 18 Aug 2004 04:13:30 GMT
www.HireAmericanCitizens.org

Quote:

> [...]
>> > > >     int (*B)[] = &A;   /* implicit cast if & is omitted */

>> > > I don't think you can declare B like that.

>> > I'm almost sure you can.  Certainly it worked in MSVC.  B's declaration
>> > doesn't actually allocate any space for the array, so there's no need
> for it
>> > to know the size, is there?

>> you can declare a pointer to an incomplete type, but even if you can,
>> you can not indirect through such a pointer. The pointer must be cast to
>> a pointer to a complete type for any indirection to be possible.
> So what's the answer to the original question, then?  -- How do you properly
> declare B to be a pointer to an array of pointers to int?

If the size isn't known, I declare B as int *(*B)[]. If the size is
known, I declare B as int *(*B)[SIZE].
I can use either one, but I can only indirect through the latter. To
indirect through the former, I must cast it to a complete pointer
type.

--

| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste       W++ B OP+                     |
\----------------------------------------- Finland rules! ------------/
"It's time, it's time, it's time to dump the slime!"
- Dr. Dante

Thu, 19 Aug 2004 00:27:54 GMT
www.HireAmericanCitizens.org

Quote:

>> So, my C class's midterm had a problem that asked us how we would declare a
>> variable B that was a pointer to an array of pointers to int.  I wrote
>>     int* (*B)[];

>> Turns out the instructor had intended
>>     int** B;

>What? B is a pointer to a pointer to int, an array does not figure into
>this at all. Either your instructor doesn't know C or you have
>misunderstood him.

Or, as Steven says next, the instructor is using a common mis-usage of
terminology.

Quote:
>> After thinking about it for a while, I've decided we're both sort of right,
>> but I thought I'd run my ideas by comp.lang.c to make sure I'm not
>> completely off base.

>> I think my answer is the technically correct one, but his reflects a common
>> (mis?)usage of the English phrase "pointer to an array" to mean a pointer to
>> the first element.

True. By far the most common way to specify an array that is to be accesed
is by using a pointer to its first element. It is qa nuisance to
says "pointyer to the first element" every time so the "to the
first element" part is often left implicit. Whether that is a
sensible thing to do in a C class or not (or indeed on comp.lang.c)
is another matter.

Quote:
>A pointer to an array is a pointer to an array, not a pointer to the
>first element. If you have an array "T []", then its first element is a
>"T", and is just as good a "T" as any other "T". Therefore a pointer to
>the first element is a "pointer to T", not a "pointer to an array of T".

Right.

Quote:
>> Simplying the problem slightly, suppose I have an array of int,
>>     int A[3] = {1, 2, 3};

>> and I decide to make a "pointer to that array".  I can write

>>     int (*B)[] = &A;   /* implicit cast if & is omitted */

This is invalid if the & is omitted because C does not permit
implicit conversion between int * and int (*)[]. If you try it your
compiler should generate a diagnostic and may legitimately refuse to
compile (i.e. reject) the code.

Quote:
>>     int* C = A;        /* implicit cast if & is present */

Similarly this is invalid if the & is added.

Quote:
>I don't think you can declare B like that. You must include the array
>size. If you say int (*B)[3]=&A then B is a pointer to an array of int,
>while C is a pointer to int.

Sure you can. int [] is a valid type in C. It is an array of unspecified
size of int and is an incomplete type. You can create a pointer to
any type in C, including incomplete types (void * is the classic example,
another is struct foo * i.e. a pointer to an incomplete structure type).

An incomplete array type is compatible with a "complete" object array type
that has the same element type. So int [] is compatible with int [3].
Two pointer types are compatible if they point to compatible types. So
int (*)[] and int (*)[3] are compatible types. C will convert implicitly
between compatible pointer types so

int (*B)[] = &A;

is a perfectly valid initialisation.

Quote:
>The fact that C and A have the same value when used as rvalues does not
>alter either's type. (Can I say either's like that?)

>> and now B and C both point to the SAME LOCATION in memory, though they
>> differ in level of indirection.

You cannot compare the values of B and C directly so it is meaningless
to say whether they point to the same location or not. The fact is that
B points to an array and C points to an int. Think of them as pointing at
the whole object and they are pointing at different things even if those
things overlap in memory. What I can say is that

(char *)B == (char *)C

which is saying that the first byte of the object that B points to
and the first byte of the object that C points to have the same
address IOW the first byte of an array is also the first byte of the
first element of the array. You could use void * instead of char * in the
expression above to mean the same thing.

Quote:
>>That is, B points to the entire array,
>> while A points to the first element.  Consequently, **B == *A.  Even more
>> weirdly, notice that (void*) &A == (void*) A.

>An array doesn't "point" anywhere. An array includes all the values, it
>doesn't point at them. But because you're using A as an rvalue, Lawrence
>Kirby's THE RULE steps in and makes A act as a pointer instead of an
>array. This doesn't mean A *is* a pointer, though.

Not my rule. :-)

--
-----------------------------------------

-----------------------------------------

Wed, 18 Aug 2004 23:03:04 GMT
www.HireAmericanCitizens.org

...

Quote:
>you can declare a pointer to an incomplete type, but even if you can,
>you can not indirect through such a pointer. The pointer must be cast to
>a pointer to a complete type for any indirection to be possible.

C does not prohibit dereferencing any pointer. You get undefined
behaviour if it doesn't point at a valid object or function, but a
pointer to an incomplete type can still point to an object. For example
in:

int (*B)[]=&A;

B points at the object A even though it doesn't regiuster how large the
object it is pointing at is.

Given that then this expression is valid:

i = (*B)[0];

and can be evaluated by applying the rules:

1. *B evaluates to an lvalue with array type.

2. As an operand of [] this is in a value context so an array lvalue is
converted to a pointer to its first element which in this case is a
pointer to the first element of A.

3. (*B)[0] accesses the first element of A.

--
-----------------------------------------

-----------------------------------------

Wed, 18 Aug 2004 23:25:23 GMT
www.HireAmericanCitizens.org

Quote:

>>An array doesn't "point" anywhere. An array includes all the values, it
>>doesn't point at them. But because you're using A as an rvalue, Lawrence
>>Kirby's THE RULE steps in and makes A act as a pointer instead of an
>>array. This doesn't mean A *is* a pointer, though.
> Not my rule. :-)

Is it Chris Torek's THE RULE, then? Off hand I only remember that both
you and Chris are High C Gurus (maybe not as high as Doug Gwyn or Phil
Plauger, but still quite high), so I may sometimes get confused which
of you said what.

--

| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste       W++ B OP+                     |
\----------------------------------------- Finland rules! ------------/
"Insanity is to be shared."
- Tailgunner

Thu, 19 Aug 2004 01:30:58 GMT
www.HireAmericanCitizens.org

Quote:

>>>An array doesn't "point" anywhere. An array includes all the values, it
>>>doesn't point at them. But because you're using A as an rvalue, Lawrence
>>>Kirby's THE RULE steps in and makes A act as a pointer instead of an
>>>array. This doesn't mean A *is* a pointer, though.

>> Not my rule. :-)

>Is it Chris Torek's THE RULE, then?

I believe so.

--
-----------------------------------------

-----------------------------------------

Fri, 20 Aug 2004 04:55:39 GMT

 Page 1 of 2 [ 15 post ]

Relevant Pages