Velocity Reviews > Re: Why C has Pointers.

# Re: Why C has Pointers.

Ben Bacarisse
Guest
Posts: n/a

 12-18-2011
ralph <(E-Mail Removed)> writes:

> On Sat, 17 Dec 2011 13:55:44 -0800, Keith Thompson <(E-Mail Removed)>
> wrote:
>
>>ralph <(E-Mail Removed)> writes:
>>[...]
>>> I have trouble understanding the constant confusion between arrays and
>>> pointers. Way back when (and we are talking many moons ago <g>) when I
>>> started out in C my mentor explained it very simply in these terms in
>>> the first couple of days.
>>>
>>> 1) There is a difference between declarations and definitions.
>>> Remember which you are dealing with and when.
>>> 2) A pointer is a "variable", an array is a "constant"

>>
>>That doesn't really make sense. An array variable is not a constant:
>>
>> int arr[10];
>> arr[5] = 42;
>>
>>I suppose what it means is that an array name, when it appears in an
>>expression (in most but not all context) decays to a pointer to the
>>array's first element, and that pointer value cannot be modified. But I
>>think that saying an array is a constant just reinforces the confusion
>>between arrays and pointers.
>>

>
> I disagree.
>
> Once the beginner gets it through his head that you can never do an
> assignment to 'arr' you resolve a ton of the questions we get around
> here. That as close to the definition of a "constant" as you can get.

I'd say that "unchanging" or "immutable" were closer definitions, and
arrays can be changed.

What you call a constant, I'd call a value, and I'd explain that
array-valued expressions are (usually) converted automatically to
pointer values.

Most people learning programming quickly get the idea of variables and
values. Variables can be assigned to, but values can't. This avoids
calling arrays "constant". It's also a start towards some more
technical matters such as why

int x;
x = 0;

is ok, but

(int)x = 0;

is not.

>>> 3) The array name evaluates to the address of the first element in the
>>> array.

>>
>>This applies to any expression of array type, not just the name of a
>>declared array object. But it doesn't apply in all contexts.
>>Specifically, an expression of array type is converted to a pointer to
>>the array object's first element *unless* it's:
>>
>> The operand of a unary "sizeof" operator (sizeof arr gives you the
>> same of the array, not of a pointer);
>>
>> The operand of a unary "&" operator (&arr gives you the address of
>> the array object; it's the same memory location as the address of
>> its first element, but it's of a different type);
>>
>> A string literal in an initializer used to initialize an array
>> object. In
>> char arr[6] = "hello";
>> the *value* of "hello" is copied into arr.
>>

>
> Yep. But what's the big deal.
>
> And of course I disagree that it actually matters to the beginner that
> the address is of a "different type". Semantically and syntactically
> it comes out the same. Plenty of time to get into vague language
> later.

I agree about putting this off, but 'arr' and '&arr' are not the same
semantically. If they were,

arr + 1

and

&arr + 1

would have the same value but they don't. (I'm using arr as defined
above.)

<snip>
>>In most contexts; see above. It would be clearer to say that an array
>>name *decays to* an address (or pointer value). And I wouldn't use the
>>word "initialized".

>
> I would. And again what does 'decay' meant to the beginner?
> In code the name "arr" is changed to, or evaluates to, the address of
> the first element.

I'd just say "converted". C has lots of automatic conversions and,
sooner or later, these need to be explains. The array to pointer
conversion fits into this general pattern.

<snip>
>>> 9) The array operator evaluates to a storage map equation, eg.
>>> type ar[i] := *(a + (i * sizeof(type))

>>
>>I'm not sure what syntax you're using. What does "type" mean here? And
>>C pointer arithmetic is already scaled by the size of the pointed-to
>>type.
>>
>>arr[i] is by definition equivalent to *(arr + i).

>
>
> You say that now, but you come back later in other response to point
> out "sizes". That "already scaled" is because the compiler knows the
> type, and he knows the type because you declared it.

It's not easy to explain the lower-level arithmetic without reference to
some particular machine. For example, on a machine with, say, byte and
word addresses, you can't describe it as you have done. By all means,
take a simple architecture and explain what a[0] means on one particular
system using addresses and size calculations, but you will also have to
explain, eventually, that arr[i] is, by definition, *(arr + i).

<snip>
--
Ben.

ralph
Guest
Posts: n/a

 12-18-2011
On Sun, 18 Dec 2011 01:26:59 +0000, Ben Bacarisse
<(E-Mail Removed)> wrote:

>ralph <(E-Mail Removed)> writes:
>
>> On Sat, 17 Dec 2011 13:55:44 -0800, Keith Thompson <(E-Mail Removed)>
>> wrote:
>>
>>>ralph <(E-Mail Removed)> writes:
>>>[...]
>>>> I have trouble understanding the constant confusion between arrays and
>>>> pointers. Way back when (and we are talking many moons ago <g>) when I
>>>> started out in C my mentor explained it very simply in these terms in
>>>> the first couple of days.
>>>>
>>>> 1) There is a difference between declarations and definitions.
>>>> Remember which you are dealing with and when.
>>>> 2) A pointer is a "variable", an array is a "constant"
>>>
>>>That doesn't really make sense. An array variable is not a constant:
>>>
>>> int arr[10];
>>> arr[5] = 42;
>>>
>>>I suppose what it means is that an array name, when it appears in an
>>>expression (in most but not all context) decays to a pointer to the
>>>array's first element, and that pointer value cannot be modified. But I
>>>think that saying an array is a constant just reinforces the confusion
>>>between arrays and pointers.
>>>

>>
>> I disagree.
>>
>> Once the beginner gets it through his head that you can never do an
>> assignment to 'arr' you resolve a ton of the questions we get around
>> here. That as close to the definition of a "constant" as you can get.

>
>I'd say that "unchanging" or "immutable" were closer definitions, and
>arrays can be changed.
>
>What you call a constant, I'd call a value, and I'd explain that
>array-valued expressions are (usually) converted automatically to
>pointer values.
>
>Most people learning programming quickly get the idea of variables and
>values. Variables can be assigned to, but values can't. This avoids
>calling arrays "constant". It's also a start towards some more
>technical matters such as why
>
> int x;
> x = 0;
>
>is ok, but
>
> (int)x = 0;
>
>is not.
>
>>>> 3) The array name evaluates to the address of the first element in the
>>>> array.
>>>
>>>This applies to any expression of array type, not just the name of a
>>>declared array object. But it doesn't apply in all contexts.
>>>Specifically, an expression of array type is converted to a pointer to
>>>the array object's first element *unless* it's:
>>>
>>> The operand of a unary "sizeof" operator (sizeof arr gives you the
>>> same of the array, not of a pointer);
>>>
>>> The operand of a unary "&" operator (&arr gives you the address of
>>> the array object; it's the same memory location as the address of
>>> its first element, but it's of a different type);
>>>
>>> A string literal in an initializer used to initialize an array
>>> object. In
>>> char arr[6] = "hello";
>>> the *value* of "hello" is copied into arr.
>>>

>>
>> Yep. But what's the big deal.
>>
>> And of course I disagree that it actually matters to the beginner that
>> the address is of a "different type". Semantically and syntactically
>> it comes out the same. Plenty of time to get into vague language
>> later.

>
>I agree about putting this off, but 'arr' and '&arr' are not the same
>semantically. If they were,
>
> arr + 1
>
>and
>
> &arr + 1
>
>would have the same value but they don't. (I'm using arr as defined
>above.)
>
><snip>
>>>In most contexts; see above. It would be clearer to say that an array
>>>name *decays to* an address (or pointer value). And I wouldn't use the
>>>word "initialized".

>>
>> I would. And again what does 'decay' meant to the beginner?
>> In code the name "arr" is changed to, or evaluates to, the address of
>> the first element.

>
>I'd just say "converted". C has lots of automatic conversions and,
>sooner or later, these need to be explains. The array to pointer
>conversion fits into this general pattern.
>
><snip>
>>>> 9) The array operator evaluates to a storage map equation, eg.
>>>> type ar[i] := *(a + (i * sizeof(type))
>>>
>>>I'm not sure what syntax you're using. What does "type" mean here? And
>>>C pointer arithmetic is already scaled by the size of the pointed-to
>>>type.
>>>
>>>arr[i] is by definition equivalent to *(arr + i).

>>
>>
>> You say that now, but you come back later in other response to point
>> out "sizes". That "already scaled" is because the compiler knows the
>> type, and he knows the type because you declared it.

>
>It's not easy to explain the lower-level arithmetic without reference to
>some particular machine. For example, on a machine with, say, byte and
>word addresses, you can't describe it as you have done. By all means,
>take a simple architecture and explain what a[0] means on one particular
>system using addresses and size calculations, but you will also have to
>explain, eventually, that arr[i] is, by definition, *(arr + i).
>

Sure it is because it ain't *(arr + i). It is ...

*(arr + ( i * sizeof(datatype)))

So for int arr[10];
arr[5] is *(arr + (5 * sizeof(int)))
byte arr[10];
arr[5] is *(arr + (5 * sizeof(byte)))

You don't care what platform you are using because the sizeof takes
care of it. sizeof and size of datatypes are defined for each compiler
(which is platform specific by default). That's how pointer arithmetic
works. That's how the C language achieves platform independence and
compilers can be implemented for any specific architecture.

88888 Dihedral
Guest
Posts: n/a

 12-18-2011
On Sunday, December 18, 2011 9:26:59 AM UTC+8, Ben Bacarisse wrote:
> ralph <(E-Mail Removed)> writes:
>
> > On Sat, 17 Dec 2011 13:55:44 -0800, Keith Thompson <(E-Mail Removed)>
> > wrote:
> >
> >>ralph <(E-Mail Removed)> writes:
> >>[...]
> >>> I have trouble understanding the constant confusion between arrays and
> >>> pointers. Way back when (and we are talking many moons ago <g>) when I
> >>> started out in C my mentor explained it very simply in these terms in
> >>> the first couple of days.
> >>>
> >>> 1) There is a difference between declarations and definitions.
> >>> Remember which you are dealing with and when.
> >>> 2) A pointer is a "variable", an array is a "constant"
> >>
> >>That doesn't really make sense. An array variable is not a constant:
> >>
> >> int arr[10];
> >> arr[5] = 42;
> >>
> >>I suppose what it means is that an array name, when it appears in an
> >>expression (in most but not all context) decays to a pointer to the
> >>array's first element, and that pointer value cannot be modified. But I
> >>think that saying an array is a constant just reinforces the confusion
> >>between arrays and pointers.
> >>

> >
> > I disagree.
> >
> > Once the beginner gets it through his head that you can never do an
> > assignment to 'arr' you resolve a ton of the questions we get around
> > here. That as close to the definition of a "constant" as you can get.

>
> I'd say that "unchanging" or "immutable" were closer definitions, and
> arrays can be changed.
>
> What you call a constant, I'd call a value, and I'd explain that
> array-valued expressions are (usually) converted automatically to
> pointer values.
>
> Most people learning programming quickly get the idea of variables and
> values. Variables can be assigned to, but values can't. This avoids
> calling arrays "constant". It's also a start towards some more
> technical matters such as why
>
> int x;
> x = 0;
>
> is ok, but
>
> (int)x = 0;
>
> is not.
>
> >>> 3) The array name evaluates to the address of the first element in the
> >>> array.
> >>
> >>This applies to any expression of array type, not just the name of a
> >>declared array object. But it doesn't apply in all contexts.
> >>Specifically, an expression of array type is converted to a pointer to
> >>the array object's first element *unless* it's:
> >>
> >> The operand of a unary "sizeof" operator (sizeof arr gives you the
> >> same of the array, not of a pointer);
> >>
> >> The operand of a unary "&" operator (&arr gives you the address of
> >> the array object; it's the same memory location as the address of
> >> its first element, but it's of a different type);
> >>
> >> A string literal in an initializer used to initialize an array
> >> object. In
> >> char arr[6] = "hello";
> >> the *value* of "hello" is copied into arr.
> >>

> >
> > Yep. But what's the big deal.
> >
> > And of course I disagree that it actually matters to the beginner that
> > the address is of a "different type". Semantically and syntactically
> > it comes out the same. Plenty of time to get into vague language
> > later.

>
> I agree about putting this off, but 'arr' and '&arr' are not the same
> semantically. If they were,
>
> arr + 1
>
> and
>
> &arr + 1
>
> would have the same value but they don't. (I'm using arr as defined
> above.)
>
> <snip>
> >>In most contexts; see above. It would be clearer to say that an array
> >>name *decays to* an address (or pointer value). And I wouldn't use the
> >>word "initialized".

> >
> > I would. And again what does 'decay' meant to the beginner?
> > In code the name "arr" is changed to, or evaluates to, the address of
> > the first element.

>
> I'd just say "converted". C has lots of automatic conversions and,
> sooner or later, these need to be explains. The array to pointer
> conversion fits into this general pattern.
>
> <snip>
> >>> 9) The array operator evaluates to a storage map equation, eg.
> >>> type ar[i] := *(a + (i * sizeof(type))
> >>
> >>I'm not sure what syntax you're using. What does "type" mean here? And
> >>C pointer arithmetic is already scaled by the size of the pointed-to
> >>type.
> >>
> >>arr[i] is by definition equivalent to *(arr + i).

> >
> >
> > You say that now, but you come back later in other response to point
> > out "sizes". That "already scaled" is because the compiler knows the
> > type, and he knows the type because you declared it.

>
> It's not easy to explain the lower-level arithmetic without reference to
> some particular machine. For example, on a machine with, say, byte and
> word addresses, you can't describe it as you have done. By all means,
> take a simple architecture and explain what a[0] means on one particular
> system using addresses and size calculations, but you will also have to
> explain, eventually, that arr[i] is, by definition, *(arr + i).
>
> <snip>
> --
> Ben.

In C there is no boundary checking in the index of an array in a read
or write operation to the array.

Seebs
Guest
Posts: n/a

 12-18-2011
On 2011-12-18, 88888 Dihedral <(E-Mail Removed)> wrote:
> In C there is no boundary checking in the index of an array in a read
> or write operation to the array.

This is a vast oversimplification. It's undefined behavior to access
outside the object. Whether or not there is bounds checking is up to the
implementation; some real implementations have done it.

-s
--
Copyright 2011, all wrongs reversed. Peter Seebach / http://www.velocityreviews.com/forums/(E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

88888 Dihedral
Guest
Posts: n/a

 12-18-2011
On Sunday, December 18, 2011 12:56:07 PM UTC+8, Seebs wrote:
> On 2011-12-18, 88888 Dihedral <(E-Mail Removed)> wrote:
> > In C there is no boundary checking in the index of an array in a read
> > or write operation to the array.

>
> This is a vast oversimplification. It's undefined behavior to access
> outside the object. Whether or not there is bounds checking is up to the
> implementation; some real implementations have done it.
>
> -s
> --

In the language design C is easy to be mixed with assembly.

If one needs boundary checking of an array, other higher level programming
languages are better options.

Seebs
Guest
Posts: n/a

 12-18-2011
On 2011-12-18, 88888 Dihedral <(E-Mail Removed)> wrote:
> In the language design C is easy to be mixed with assembly.

That, too, is an oversimplification.

> If one needs boundary checking of an array, other higher level programming
> languages are better options.

Could be, but the fact is, there are bounds-checking implementations. The
claim that there's no bounds-checking in C is not really generally true.

-s
--
Copyright 2011, all wrongs reversed. Peter Seebach / (E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

Philip Lantz
Guest
Posts: n/a

 12-18-2011
On Sat, 17 Dec 2011, ralph wrote:
> On Sun, 18 Dec 2011, Ben Bacarisse wrote:
>> ... arr[i] is, by definition, *(arr + i).
>>

>
> ... it ain't *(arr + i). It is ...
>
> *(arr + ( i * sizeof(datatype)))
>
> So for int arr[10];
> arr[5] is *(arr + (5 * sizeof(int)))
> byte arr[10];
> arr[5] is *(arr + (5 * sizeof(byte)))
>
> You don't care what platform you are using because the sizeof takes
> care of it. sizeof and size of datatypes are defined for each compiler
> (which is platform specific by default). That's how pointer arithmetic
> works. That's how the C language achieves platform independence and
> compilers can be implemented for any specific architecture.

Ralph, could you do me a favor, please, and run the following program,
and let us know what its output is for you?

#include <stdio.h>

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

printf("%d\n", arr[2]);
printf("%d\n", *(arr + (2 * sizeof(int))));
printf("%d\n", *(arr + 2));

return 0;
}

Thanks.

Philip

P.S. I get:
3
17
3

Ben Bacarisse
Guest
Posts: n/a

 12-18-2011
ralph <(E-Mail Removed)> writes:

> On Sun, 18 Dec 2011 01:26:59 +0000, Ben Bacarisse
> <(E-Mail Removed)> wrote:
>
>>ralph <(E-Mail Removed)> writes:
>>
>>> On Sat, 17 Dec 2011 13:55:44 -0800, Keith Thompson <(E-Mail Removed)>

<snip>
>>>>arr[i] is by definition equivalent to *(arr + i).
>>>
>>>
>>> You say that now, but you come back later in other response to point
>>> out "sizes". That "already scaled" is because the compiler knows the
>>> type, and he knows the type because you declared it.

>>
>>It's not easy to explain the lower-level arithmetic without reference to
>>some particular machine. For example, on a machine with, say, byte and
>>word addresses, you can't describe it as you have done. By all means,
>>take a simple architecture and explain what a[0] means on one particular
>>system using addresses and size calculations, but you will also have to
>>explain, eventually, that arr[i] is, by definition, *(arr + i).
>>

>
> Sure it is because it ain't *(arr + i). It is ...
>
> *(arr + ( i * sizeof(datatype)))
>
> So for int arr[10];
> arr[5] is *(arr + (5 * sizeof(int)))
> byte arr[10];
> arr[5] is *(arr + (5 * sizeof(byte)))

That's wrong, if what you are writing there are C expressions. arr[5]
is defined to be the same as *(arr + 5). Can you clear this up? Do you
agree that

arr[5] == *(arr + 5)

and

&arr[5] == arr + 5

are C expressions that always evaluate to 1? (Let's assume arr[5] has
been assigned some non-trap representation!)

You may be trying to explain arr[5] using a confusingly C-like
notation. If so, that's a very confusing thing to do. If I wanted to
explain what a compiler has to do, I'd use some entirely un-C-like
notation to avoid any possible misunderstanding.

> You don't care what platform you are using because the sizeof takes
> care of it. sizeof and size of datatypes are defined for each compiler
> (which is platform specific by default). That's how pointer arithmetic
> works.

Not always. It's not sizeof that takes care of it, it's the compiler.
A C compiler must ensure that arr[i] and *(arr + i) have the same
meaning. To do that, it must do something with machine addresses that
involves the size of the array elements, but it's not always as simple
as you suggest. For example, I've used a machine where sizeof(int) is 2
but arr[5] (where arr is your int array from above) is implemented by
adding 5 (yes, 5, not 2*5) to the address of the array's first element.

> That's how the C language achieves platform independence and
> compilers can be implemented for any specific architecture.

It's more subtle than that. The address arithmetic is related to the
size but it need not be exactly as you describe.

--
Ben.

88888 Dihedral
Guest
Posts: n/a

 12-18-2011
On Sunday, December 18, 2011 1:42:59 PM UTC+8, Seebs wrote:
> On 2011-12-18, 88888 Dihedral <(E-Mail Removed)> wrote:
> > In the language design C is easy to be mixed with assembly.

>
> That, too, is an oversimplification.
>
> > If one needs boundary checking of an array, other higher level programming
> > languages are better options.

>
> Could be, but the fact is, there are bounds-checking implementations. The
> claim that there's no bounds-checking in C is not really generally true.
>
> -s

If there is any boundary checking on a machine,
what does that mean in the execution speed?

Happy programming?

James Kuyper
Guest
Posts: n/a

 12-18-2011
On 12/17/2011 11:34 PM, ralph wrote:
....
> So for int arr[10];
> arr[5] is *(arr + (5 * sizeof(int)))

Other people have told you that this is wrong, and have cited the
relevant parts of the standard to prove it. If your compiler implements
a[i] as meaning anything other than *(a+i), it's not a conforming
implementation of C (or C++, or any of several other C-like languages).

However, a couple of casts would make it correct:

arr[5] == *(int*)((char*)arr + (5 * sizeof(int)));

When you understand precisely why the casts make a difference, you'll
have a much better understanding of C arrays and pointers than you
currently appear to have.

> byte arr[10];
> arr[5] is *(arr + (5 * sizeof(byte)))

You haven't provided a typedef for 'byte', but is seems likely, given
the name, that sizeof(byte) == 1. If that's true, than so is your
statement above. Otherwise, it's false.
--
James Kuyper