I am having a confusing time with understanding arrays and variables because of this reasoning:

Variables are aliases for memory locations and array name is the address of the first element of the array then why are variables not accesssed as

*i

whereas the first element of array is accessed as:

*(array-name +0)

????

The issue is not between arrays and other variables in general, but arrays and pointers to said arrays. An array is not a pointer; it is a regular variable, just one which names a block of values rather than a single value. The usual syntax for accessing the elements of an array is

int ary[16];

ary[0] = 17;  /* the 0th element of ary is now 17 */

OK, a quick explanation. A pointer, if you are unfamiliar, is a variable that holds an address in memory, and can be used to refer to this address. Pointers have types, like any other variable, which is a 'pointer to the declared type'. In the following code,

int a, *ptr1, *ptr2;

the type of a is int, while the type of ptr1 and ptr2 is 'pointer to int'. See? The pointer has to know the size of the variable it is pointing to, hence the need for typed pointers.

To use a pointer, you need to get a reference to the variable in question, using the dereference operator, &, like so:

ptr1 = &a;

You now can access the value of a through ptr using the indirection operator:

*ptr1 = 42;   /* the value of a is now 42 */

To pass an address from one pointer to another, you would just assign it like normal:

ptr2 = ptr1;  /* both now point to a */

However, when an array is passed to a pointer of the appropriate type,

int i, ary[16], *ptr;   /* remember, ptr is a pointer to int here */
ptr = ary;

The compiler assumes that, unlike with a non-array variable, you always want to de-reference an array, so the compiler obligingly does so. You can then use the pointer to walk through the array:

for (i = 0; i < 16; i++) {
    *(ptr + i) = i * i;     /* populate the array w/ the squares */
}

Conversely, you can use array indexing on a pointer,

for (i = 0; i < 16; i++) {
    ptr[i] = i * i;     /* populate the array w/ the squares */
}

The difference is mostly negligible, though the index operation can be a little slower in some cases due to differences in overhead.

Great post Schol-R-LEA, but I have one very minor correction:

An array is not a pointer; it is a regular variable, just one which names a block of values rather than a single value

Actually, an array is implicitly a pointer, it can be considered to be a pointer to the first element (element 0) of the block of memory reserved for the array. So if you have an array of integers, the array variable is also implicitly an int pointer.

To demonstrate the point here's a simple, yet completely impractical and contrived example:

#include <stdio.h>

/* Initialise an array of ints with a set value
 * \param <ptr> pointer to first element
 * \param <size> size of array
 * \param <val> value to initialise array with
 */
void initialiseArray(int *ptr, int size, int val)
{
    int count;
    for(count=0;count<size;++count)
    {
        *ptr = val;
        ++ptr;
    }
}

/* Modify the value held by an int pointer
 * \param <ptr> pointer to value
 * \param <val> new value
 */
void modifyValue(int *ptr, int val)
{
    *ptr = val;
}

int main()
{
    const int size = 5;
    int iArray[size];
    int count;

    /* initialise all elements of the array with the value 999
     * Note: passing the array variable, because it is implicitly an int pointer */
    initialiseArray(iArray, size, 999);

    /* This will let us pass the first element of the array to the modify function */
    modifyValue(iArray, 25);

    /* In order to pass a specific element to the modify function we need to use the address of operator (&)
     * because the square brackets dereference the variable at iArray[2], yielding an int, not an int pointer */
    modifyValue(&iArray[2], 325);

    /* or we can use pointer arithmetic to pass a specific element, in this case the last element: */
    modifyValue(iArray+size-1, 440);

    /* Now let's see what is in the array */
    printf("Final content of array:\n");
    for(count=0;count<size;++count)
        printf("%d\n", iArray[count]);

    return 0;
}

That should compile and run without errors on any C compiler. Works for me on gcc/mingw in Linux and Windows. As for whether or not it is good practice to abuse arrays in this manner, IDK. But it wasn't a real-world usage, it was just to demonstrate the point that an array variable is also implicitly a pointer!

Going back to the OPs post:

With ordinary variables, you have direct access to the value held by the variable, there is no need to dereference using the * operator.

Whereas as Schol-R-Lea explained, pointers do not hold values, they hold the memory address of the value they point to. In order to access the value pointed to by a pointer, you need to dereference the pointer using the * operator.

Going back to arrays, and putting my previous post into context.
In order to dereference an element in an array, it is most common to use square brackets:
int val = someArray[idx];

But because arrays are technically pointers, you can also use the dereference operator and pointer arithmetic:
int val = *(someArray+idx);

Both are valid. But for clarity, most people use square brackets to dereference values in arrays.

Edited 1 Year Ago by JasonHippy

JasonHippy: This is actually a subtle point, and one that need to be understood: arrays are not pointers, but when used in certain ways will automatically be 'devolved' to pointers (cast, basically) by the compiler so that they can be treated interchangeably with pointers. The array variable name is still a name for the block of memory; there is no separate pointer value pointing to the memory block. The interchangability of arrays and pointers is syntactic sugar, not a reflection of the actual layout in memory.

Edited 1 Year Ago by Schol-R-LEA

This article has been dead for over six months. Start a new discussion instead.