Velocity Reviews > Array and Pointer Tutorial

Array and Pointer Tutorial

Tomás
Guest
Posts: n/a

 05-11-2006
Some programmers treat arrays just like pointers (and some even think that
they're exactly equivalent). I'm going to demonstrate the differences.

Firstly, let's assume that we're working on a platform which has the
following properties:

1) char's are 8-Bit. ( "char" is synomonous with "byte" ).
2) int's are 32-Bit. ( sizeof(int) == 4 ).
3) Pointers are 64-Bit. ( sizeof(int*) == 8 ).

First let's make two declarations:

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

int* const pointer = (int*)malloc( 5 * sizeof(int) );
}

Now I'll demonstrate how "array" and "pointer" are different:

I'll start off with simple analgous expressions:

================================================== ==========================
| Expression | Type and Access Specifiers | That in English |
================================================== ==========================
| | | |
| array | int[5] | An array of five int's.|
| | | |
|---------------------------------------------------------------------------
| | |A const pointer which |
| pointer | int* const |points to a modifiable |
| | |int. |
|--------------------------------------------------------------------------|
| | |A const pointer which |
| &array | int (* const)[5] |points to a modifiable |
| | |array of five int's. |
|--------------------------------------------------------------------------|
| | |A const pointer, which |
| &pointer | int* const* const |points to a const |
| | |pointer, which points to|
| | |a modifiable int. |
================================================== ==========================

Here's how "sizeof" works with them:

================================================== =========
| Expression | sizeof( exp ) | But Why? |
================================================== =========
| | | |
| array | 20 | It's five int's. |
| | (5 * 4) | |
|---------------------------------------------------------|
| | | |
| pointer | 8 | It's just a pointer.|
| | (just | |
|---------------------------------------------------------|
| | | |
| &array | 8 | It's just a pointer.|
| | (just | |
|----------------------------------------------------------
| | | |
| &pointer | 8 | It's just a pointer.|
| | | |
| | (just | |
================================================== =========

Okay next thing to discuss is the usage of square brackets, and the
dereference operator. The two of these are to be used by pointers only. So
how come we can use them with arrays, as follows?:

array[0] = 4;

*array = 6;

The reason is that an expression of the following type:

int[5]

can implicitly convert to an expression of the following type:

int* const

What it does is convert to a pointer to the first element of the array.
Therefore, the first example:

array[0] = 4;

implicitly converts "array" to a normal pointer, then uses chain brackets to
access memory at a certain offset from the original address.

Also the second example:

*array = 6;

implicitly converts "array" to a normal pointer, then dereferences it.

NOTE: You must remember that an array implicitly converts to a pointer to
its first element, NOT to a pointer to the array. This fact has a few
implications. Here's one such implication:

*(array + 3) = 6;

What the above line of code does is the following:

1) Implicitly converts "array" to an: int* const
3) Dereferences the resulting pointer, and assigns 6 to it.

If "array" implicitly converted to: int (*)[5]
rather than a pointer to the first element, then Step 2 above would be
different, specifically:

And we know that sizeof(int[5]) is 20 on this platform (not 8!).

So you may ask, "What's the point in having a pointer to an array?" -- well
here's where it may come in handy:

void SomeFunc ( int (* const p_array)[5] )
{
(*p_array)[0] = 99;
(*p_array)[1] = 98;
(*p_array)[2] = 97;
(*p_array)[3] = 96;
(*p_array)[4] = 95;

/* This function won't accept an array of any
other size! */
}

And here's a C++-specific example with references:

void SomeFunc ( int (&array)[5] )
{
array[0] = 99;
array[1] = 98;
array[2] = 97;
array[3] = 96;
array[4] = 95;

/* This function won't accept an array of any
other size! */
}

Also in C++, you can exploit the use of templates:

template<class T, unsigned long len>
void KeepCopy( const T (&array)[len] )
{
static my_array[len];

/* Do some other stuff */
}

I've posted this to a few newsgroups, so if you'd like to reply, please post
to comp.lang.c because it's the common denominator. If your post is C++-
specific, the please post to comp.lang.c++.

Did I leave anything out?

-Tomás

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
--
comp.lang.c.moderated - moderation address: http://www.velocityreviews.com/forums/(E-Mail Removed) -- you must
or the newsgroup name in square brackets in the subject line. Sorry.

Richard Bos
Guest
Posts: n/a

 05-11-2006
"Tomás" <(E-Mail Removed)> wrote:

> Some programmers treat arrays just like pointers (and some even think that
> they're exactly equivalent). I'm going to demonstrate the differences.
>
> Firstly, let's assume that we're working on a platform which has the
> following properties:
>
> 1) char's are 8-Bit. ( "char" is synomonous with "byte" ).

A char is _always_ a byte. What you mean is that you are assuming a char
(and therefore also a byte) to be equal to an octet.

> 2) int's are 32-Bit. ( sizeof(int) == 4 ).
> 3) Pointers are 64-Bit. ( sizeof(int*) == 8 ).

> First let's make two declarations:
>
> int main(void)
> {
> int array[5];
>
> int* const pointer = (int*)malloc( 5 * sizeof(int) );

*Boing* and here the demonstration crashes.

Never cast malloc(). It is not necessary. void *s can be freely
converted to and from any object pointer type.
Never use malloc() (or any other function, for that matter) without a
proper declaration in scope. It forces your compiler to assume that the
function returns an int, which malloc() clearly does not.

Note that the first error hides the second. The combination of the two
can result in garbage being assigned to your pointer.

As a matter of convenient maintenance, not a true error, it is more
dabble-proof to use sizeof *pointer rather than sizeof (type). If your
pointer's type changes, the first form stays correct, the second can
turn deceptively (and hiddenly!) broken.

All in all, that program should've looked like this:

#include <stdlib.h>

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

int* const pointer = malloc(5 * sizeof *pointer);
}

Anyway, the difference between pointers and arrays is most simply
demonstrated using the age[1]-old method of arrows and groups of boxes.

Richard

[1] I.e., in the computing world, a couple of decades

=?ISO-8859-15?Q?Juli=E1n?= Albo
Guest
Posts: n/a

 05-11-2006
Tomás wrote:

> Some programmers treat arrays just like pointers (and some even think that
> they're exactly equivalent). I'm going to demonstrate the differences.

Some of these days you can also write an article demonstrating that integer
types are not floating point types. It will be another great contribution
to the progress of humanity.

--
Salu2

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php

Guest
Posts: n/a

 05-11-2006

> As a matter of convenient maintenance, not a true error, it is more
> dabble-proof to use sizeof *pointer rather than sizeof (type). If your
> pointer's type changes, the first form stays correct, the second can
> turn deceptively (and hiddenly!) broken.
>
> All in all, that program should've looked like this:
>
> #include <stdlib.h>
>
> int main(void)
> {
> int array[5];
>
> int* const pointer = malloc(5 * sizeof *pointer);
> }
>
> Anyway, the difference between pointers and arrays is most simply
> demonstrated using the age[1]-old method of arrows and groups of boxes.
>
> Richard
>
> [1] I.e., in the computing world, a couple of decades

Okay, I'm probably missing this. But say I have the following:

/*I omitted checking for NULL and using free*/

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

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

int *q = malloc(sizeof *array);

return 0;
}

Now, I change
int array[5];

to

double array[5];

Wouldn't the sizeof double be truncated to the sizeof int? If so, the
wouldn't this create an additional bug?

CBFalconer
Guest
Posts: n/a

 05-11-2006
>

.... snip ...
>
> Okay, I'm probably missing this. But say I have the following:
>
> /*I omitted checking for NULL and using free*/
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void) {
> int array[5];
>
> int *q = malloc(sizeof *array);

There is no such thing as *array. array is an array of 5 integers,
not a pointer.

--
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html

Flash Gordon
Guest
Posts: n/a

 05-11-2006
>> As a matter of convenient maintenance, not a true error, it is more
>> dabble-proof to use sizeof *pointer rather than sizeof (type). If your
>> pointer's type changes, the first form stays correct, the second can
>> turn deceptively (and hiddenly!) broken.
>>
>> All in all, that program should've looked like this:
>>
>> #include <stdlib.h>
>>
>> int main(void)
>> {
>> int array[5];
>>
>> int* const pointer = malloc(5 * sizeof *pointer);
>> }
>>
>> Anyway, the difference between pointers and arrays is most simply
>> demonstrated using the age[1]-old method of arrows and groups of boxes.
>>
>> Richard
>>
>> [1] I.e., in the computing world, a couple of decades

>
> Okay, I'm probably missing this. But say I have the following:
>
> /*I omitted checking for NULL and using free*/
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void) {
> int array[5];
>
> int *q = malloc(sizeof *array);
>
> return 0;
> }
>
>
> Now, I change
> int array[5];
>
> to
>
> double array[5];
>
> Wouldn't the sizeof double be truncated to the sizeof int? If so, the
> wouldn't this create an additional bug?

You have not followed the suggested practice of using sizeof *pointer
being assigned to. Your example should have been:
#include <stdlib.h>

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

int *q = malloc(sizeof *q);

return 0;
}

Or, if you want array and q to always be the same type, you could have used:
#include <stdlib.h>
int main(void) {
int array[5], *q = malloc(sizeof *q);

return 0;
}

I really can't see why you would think of using sizeof some other object.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php

Charles Richmond
Guest
Posts: n/a

 05-11-2006
CBFalconer wrote:
>
> >

> ... snip ...
> >
> > Okay, I'm probably missing this. But say I have the following:
> >
> > /*I omitted checking for NULL and using free*/
> >
> > #include <stdio.h>
> > #include <stdlib.h>
> >
> > int main(void) {
> > int array[5];
> >
> > int *q = malloc(sizeof *array);

>
> There is no such thing as *array. array is an array of 5 integers,
> not a pointer.
>

"array[0]" is the same as "*(array+0)" which simplifies to "*array".

--
+----------------------------------------------------------------+
| Charles and Francis Richmond richmond at plano dot net |
+----------------------------------------------------------------+

CBFalconer
Guest
Posts: n/a

 05-11-2006
Charles Richmond wrote:
> CBFalconer wrote:
>> >

>> ... snip ...
>>>
>>> Okay, I'm probably missing this. But say I have the following:
>>>
>>> /*I omitted checking for NULL and using free*/
>>>
>>> #include <stdio.h>
>>> #include <stdlib.h>
>>>
>>> int main(void) {
>>> int array[5];
>>>
>>> int *q = malloc(sizeof *array);

>>
>> There is no such thing as *array. array is an array of 5 integers,
>> not a pointer.

>
> "array[0]" is the same as "*(array+0)" which simplifies to "*array".

When array is passed as a parameter, which this one isn't.

--
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html

pete
Guest
Posts: n/a

 05-11-2006
CBFalconer wrote:
>

> > int array[5];
> >
> > int *q = malloc(sizeof *array);

>
> There is no such thing as *array. array is an array of 5 integers,
> not a pointer.

(*array) is an expression of type int.

The operand of sizeof is (*array), not (array),
so, array gets converted to a pointer.

--
pete

Tomás
Guest
Posts: n/a

 05-12-2006
CBFalconer posted:

>> "array[0]" is the same as "*(array+0)" which simplifies to "*array".

>
> When array is passed as a parameter, which this one isn't.

Stop trolling and propogating misinformation.

"array" implicitly converts to a pointer to its first element ALL THE TIME
-- NOT just when passed as an argument to a function, NOT just when it's a
global variable, NOT just when you have porridge instead of cereal.

-Tomás