Blessen George
Blessen George

Reputation: 270

What's the difference between the types - int * and int *[100] in C?

Kinda of a noob so don't kill me here.

What's the difference between the following codes?

int *p;         //As i understand, it creates a pointer to an variable of size int.
int *p[100];    //Don't really know what this is.
int (*p)[100];  // I have come to understand that this is a pointer to an array. 

Upvotes: 12

Views: 7533

Answers (4)

Mike
Mike

Reputation: 49393

Sounds like you could use an introduction to the Spiral Rule.

Start at the variable and "spiral" your way around right to left:

              +-------+
              | +--+  |             // So we have:
              | |  |  |                    p    // p     
          int * p  |  |                  * p    // p is a pointer
           ^  ^    |  |              int * p    // p is a pointer to an int
           |  +----+  |
           +----------+

Next one:

              +--------+
              | +--+   |         p       // p
              | |  V   |         p[100]  // p is an array of 100
          int * p[100] |       * p[100]  // p is an array of 100 pointers
           ^  ^    |   |   int * p[100]  // p is an array of 100 pointers to ints
           |  +----+   |
           +-----------+

Finally, a new part of the rule, do anything in parenthesis first:

                   +-----+            
                   | +-+ |    
                   | ^ | |         ( p)       // p
              int (* p)  [100];    (*p)       // p is a pointer
               ^   ^   | |         (*p)[100]  // p is a pointer to an array of 100
               |   +---+ |     int (*p)[100]  // p is a pointer to an array of 100 ints
               +---------+    

If you're online/have access to a computer, it's always usefule to use the cdecl.org site, but it's important to be able to read code offline as well, and this rule will let you do just that.

Upvotes: 19

Eric Lippert
Eric Lippert

Reputation: 660034

Kinda of a noob so don't kill me here

Working out what a type means in C can be tricky even for experts. No worries.

What's the difference between the following codes?

The other answers are good and I have no intention of contradicting them. Rather, here's yet another way to think about it. We need to define three things:

  • A variable is a thing that supports three operations. The fetch operation takes a variable and produces its current value. The fetch operation has no notation; you simply use the variable. The store operation takes a variable and a value, and stores the value in the variable. The address operation takes a variable and produces a pointer.

  • A pointer is a thing that supports one operation. The dereference operation, written as prefix *pointer, takes a pointer and produces a variable. (Pointers support other operations such as arithmetic and indexing -- which is a form of arithmetic -- but let's not go there.)

  • An array is a thing that supports one operation. The index operation takes an array and an integer and produces a variable. It's syntax is postfix: array[index]

OK, so now we come to your question. What does the declaration

int p;

mean? That the expression p is a variable of type int. Note that this is a variable; you can store things to p. What does the declaration

int *p;

mean? That the expression *p is a variable of type int. Now that we know that we can deduce what p is. Since *p is a dereference and produces a variable, p must be a pointer to int. What does the declaration

int *p[100];

mean? It means that *the expression *p[i] is a variable of type int provided that i is an integer value from 0 to 99. We got a variable out, but we could have gotten there from either the pointer or the array, so we have to figure out which. We consult the operator precedence table and discover that the indexing operator binds "tighter" than the dereferencing operator. That is:

*p[i]

is the same thing as

*(p[i])

and remember, that thing is a variable of type int. The contents of the parens are dereferenced to produce a variable of type int so the contents of the parens must be a pointer to int. Therefore

p[i]

is a pointer to int. How is that possible? This must be a fetch of a variable of type pointer-to-int! So p[i] is a variable of type pointer to int. Since this is an index operation, p must be an array of pointers to int.

Now you do the next one.

int (*p)[100];

means what?

Upvotes: 9

Joseph Mansfield
Joseph Mansfield

Reputation: 110658

  1. This is a pointer to an int:

    int *p;
    
    ┌────┐
    │int*│
    └────┘
    

    It should point at an int, something like this:

    ┌────┐
    │int*│
    └─┃──┘
      ▼
    ┌───┐
    │int│
    └───┘
    
  2. This is an array of 100 pointers to int:

    int *p[100];
    

    That is, it gives you 100 pointers.

    ┌────┬────┬────┬────┬────┬────┬┄
    │int*│int*│int*│int*│int*│int*│
    └────┴────┴────┴────┴────┴────┴┄
    

    Each pointer should point an int, perhaps like this:

    ┌────┬────┬────┬────┬────┬────┬┄
    │int*│int*│int*│int*│int*│int*│
    └─┃──┴─┃──┴─┃──┴─┃──┴─┃──┴─┃──┴┄
      ▼    ▼    ▼    ▼    ▼    ▼
    ┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌┄
    │int││int││int││int││int││int││
    └───┘└───┘└───┘└───┘└───┘└───┘└┄
    

    Of course, there's no reason they can't all point at the same int, or whatever.

    You may want to use an array of pointers if you want many pointers that you can easily iterate over. You may, for example, dynamically allocate objects and have each pointer point at a different object:

    p[0] = new int(0);
    p[1] = new int(0);
    // ...
    

    Perhaps dynamically allocating ints isn't the best example, but I think the point is clear.

  3. This is a pointer to an array of 100 int:

    int (*p)[100];
    

    That is, it gives you just 1 pointer:

    ┌───────────┐
    │int(*)[100]│
    └───────────┘
    

    It should point at an array that contains 100 ints:

    ┌───────────┐
    │int(*)[100]│
    └─┃─────────┘
      ▼
    ┌───┬───┬───┬───┬───┬───┬┄
    │int│int│int│int│int│int│
    └───┴───┴───┴───┴───┴───┴┄
    

    You will get a pointer to an array when you use the address-of operator (&) on the name of an array. For example:

    int arr[100] = { /* some initial values */ };
    int (*p)[100] = &arr;
    

    Here, I've taken the address of the arr array, which gives me a pointer to that array. If you then want to access an element of the array, you have to dereference the pointer first: (*p)[3] will access element 3.


Side note:

Always remember that arrays are not pointers. As we have just seen, we can take the address of an array to get a pointer to it, just like any other (non-temporary) object in C++. The only special connection between arrays and pointers is that the name of an array can be implicitly converted to a pointer to the array's first element. That means the following is valid:

int arr[100] = { /* some initial values */ };
int* p = arr;

The pointer p will point at the first element in arr. Note that p is not a pointer to the array, but a pointer to an element of the array.

(Also note that there is no such thing as an array type function argument. If you write something like int p[] as a function argument, it is transformed by the compiler to be a int*.)

Upvotes: 41

haccks
haccks

Reputation: 106012

int *p; --> Declares a pointer to an integer type.
int *p[100]; -->Declares an array of 100 pointers to integer type.
int (*p)[100]; --> Declares a pointer to an array of 100 integers.

Use cdecl for translating such types.

Upvotes: 4

Related Questions