0

I am a total beginner to C so please, work with my ignorance. Why does a normal pointer

int* ptr = &a; has two spaces in memory (one for the pointer variable and one for the value it points to) and an array pointer int a[] = {5}; only has one memory space (if I print out

printf("\n%p\n", a) I get the same address as if I printed out: printf("\n%p\n", &a).

The question is, shouldn't there be a memory space for the pointer variable a and one for its value which points to the first array element? It does it with the regular pointer int* ptr = &a;

polymorph
  • 79
  • 9
  • Your first example has only one "space" -- that for the pointer itself. `a` is defined elsewhere. But important to remember is that a C pointer contains no indication as to the size of the array it addresses, if it even addresses an array. – Hot Licks Apr 17 '14 at 18:53
  • 1
    (You can't really begin to understand C pointers until you set aside any expectation that they're "logical".) – Hot Licks Apr 17 '14 at 18:54
  • You have to keep in mind if `a` is declared as an array, then `a` is notationally same as `&a`. – Brandin Apr 17 '14 at 18:56
  • 1
    @HotLicks Licks I am sure that if they were engineer by one person, another person can understand them as well. You really did not provide me with a helpful answer but thank you. – polymorph Apr 17 '14 at 18:57
  • @polymorph That's just the rule. If `arr` is an array, typing `arr` gives you a pointer to the first element. If you take the address of `arr` you also get a pointer to the first element. – Brandin Apr 17 '14 at 19:01
  • The main thing to understand is that there's really no such thing as a "array pointer" in C. There's barely a concept of an array. – Hot Licks Apr 17 '14 at 20:27

6 Answers6

2

It's a little unclear from your question (and assuming no compiler optimization), but if you first declare a variable and then a pointer to that variable,

int a = 4;
int *p = &a;

then you have two different variables, it makes sense that there are two memory slots. You might change p to point to something else, and still want to refer to a later

int a = 4;
int b = 5;

int *p = &a; // p points to a

// ...

p = &b; // now p points to b
a = 6; // but you can still use a

The array declaration just allocates memory on the stack. If you wanted to do the same with a pointer, on the heap, you would use something like malloc or calloc (or new in c++)

int *p = (int*)malloc(1 * sizeof(int));
*p = 4;

but of course remember to free it later (delete in c++)

free(p);
p = 0;
duncan
  • 446
  • 3
  • 7
  • What I still don't understand is where the `a` variable lives. If the pointer has an address for itself and one for its value, why doesn't `a`? – polymorph Apr 17 '14 at 19:14
  • Every variable has an address (again assuming no compiler optimizations). Both ````a```` and ````p```` are regular variables. The value of a is 4. The value of p is the address of a. Make sense? – duncan Apr 17 '14 at 19:16
  • Right, we established that `a` has an address but shouldn't its value which it points to, also have an address? `p` like `a` has an address but one for its value as well, which is `a` but `a` has the same address for its value and itself? – polymorph Apr 17 '14 at 19:19
  • I think you're over-thinking it. On a 32-bit system, the type of int and * are essentially the same thing - they're 4-byte values. Both ````a```` and ````p```` refer to one 4-byte slot in memory. In the ````a```` slot is the value 4; and in the ````p```` slot is the value 0xfffa or something, which is the address of a. – duncan Apr 17 '14 at 19:23
  • A pointer is a type in C, which means it has special semantics, but that is a function of the language and not the actual memory. You can use an int as a pointer if you want, e.g. ````int a = 3; *(&a) = 4;```` although it will almost certainly segfault, or worse. – duncan Apr 17 '14 at 19:24
  • I get it, I do tend to overthink these things and lose myself in the process. Thank you. – polymorph Apr 17 '14 at 19:27
  • @polymorph a ends up being a constant pointing to the first memory location of the array. – Tarik Apr 17 '14 at 19:27
1

The main misunderstanding here is that &a return not pointer to pointer as it expected that's because in C language there some difference between [] and * (Explanation here: Difference between [] and *) If you try to &a if a was an pointer (e.g. int *a) then you obtain a new memory place but when your use a static array (i.e. int a[]) then it return address of the first array element. I'll also try to clarify this by mean of the next code block.

#include <stdio.h>

int main(int argc, char *argv[])
{
    // for cycles
    int k; 

    printf("That is a pointer case:\n");
    // Allocate memory for 4 bytes (one int is four bytes on x86 platform, 
    // can be differ for microcontroller e.g.)
    int c = 0xDEADBEEF;
    unsigned char *b = (unsigned char*) &c;
    printf("Value c: %p\n", c);
    printf("Pointer to c: %p\n", &c);
    printf("Pointer b (eq. to c): %p\n", b);
    // Reverse order (little-endian in case of x86)
    for (k = 0; k < 4; k++)
        printf("b[%d] = 0x%02X\n", k, b[k]);

    // MAIN DIFFERENCE HERE: (see below)    
    unsigned char **p_b = &b;
    // And now if we use & one more we obtain pointer to the pointer
    // 0xDEADBEEF <-- b <-- &p_b
    // This pointer different then b itself
    printf("Pointer to the pointer b: %p\n", p_b);

    printf("\nOther case, now we use array that defined by []:\n");
    int a[] = {5,1};
    int *ptr = &a;
    // 'a' is array but physically it also pointer to location
    // logically it's treat differ other then real pointer
    printf("'a' is array: %x\n", a);
    // MAIN DIFFERENCE HERE: we obtain not a pointer to pointer
    printf("Pointer to 'a' result also 'a'%x\n", &a);
    printf("Same as 'a': %x\n", ptr);
    printf("Access to memory that 'a' pointes to: \n%x\n", *a);

    return 0;
}
Community
  • 1
  • 1
mblw
  • 1,762
  • 1
  • 19
  • 28
0

This is very simple. In first case,

int* ptr = &a;

you have one variable a already declared and hence present in memory. Now you declare another variable ptr (to hold the address, in C variables which hold address of another variable are called pointers), which again requires memory in the same way as a required.

In second case,

int a[] = {5};

You just declare one variable (which will hold a collection of ints), hence memory is allocated accordingly for a[].

0xF1
  • 6,046
  • 2
  • 27
  • 50
0

In this expression, int* p = &a; p has only one memory location, of the WORD size of your CPU, most probably, and it is to store the address (memory location) of another variable.

When you do *p you are dereferencing p, which means you are getting the value of what p points to. In this particular case that would be the value of a. a has its own location in memory, and p only points to it, but does not itself store as content.

When you have an array, like int a[] = {5};, you have a series (or one) of memory locations, and they are filled with values. These are actual locations.

Arrays in C can decay to a pointer, so when you printf like you did with your array, you get the same address, whether you do a or &a. This is because of array to pointer decay.

a is still the same location, and is only that location. &a actually returns a pointer to a, but that pointer sits else where in memory. If you did int* b = &a; then b here would not have the same location as a, however, it would point to a.

Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
  • Dereferencing is with `*` and `&` takes the address. – Jamie Apr 17 '14 at 18:57
  • a is the address of the first element of the array. In that sense, C is somewhat forgiving by allowing &a which would mean address of address of first element of array. Not necessarily consistent but accepted by the compiler. – Tarik Apr 17 '14 at 19:01
  • @Jamie yes you're right. I'm derping. I fixed it now. – Tony The Lion Apr 17 '14 at 19:02
  • @TonyTheLion Removed the down vote; also "`p`" doesn't exist in the example you give, `ptr` does. – Jamie Apr 17 '14 at 19:03
  • "*a actually returns a pointer to a". Nope, it returns the value of the first element of a. – Tarik Apr 17 '14 at 19:04
0

ptr is a variable containing a memory address. You can assign various memory addresses to ptr. a is a constant representing a fixed memory address of the first element of the array. As such you can do:

ptr = a;

but not

a = ptr;
Tarik
  • 10,810
  • 2
  • 26
  • 40
-1

Pointers point to an area in memory. Pointers to int point to an area large enough to hold a value of int type.

If you have an array of int and make a pointer point to the array first element

int array[42];
int *p = array;

the pointer still points to a space wide enough for an int.

On the other hand, if you make a different pointer point to the whole array, this new pointer points to a larger area that starts at the same address

 int (*q)[42]; // q is a pointer to an array of 42 ints
 q = &array;

the address of both p and q is the same, but they point to differently sized areas.

pmg
  • 106,608
  • 13
  • 126
  • 198
  • Emphasis: the pointer storage in both cases is the same, what they point _too_ is different. – Jamie Apr 17 '14 at 19:01
  • Nope. Even in the first case, p[10] is perfectly legal and equivalent to array[10]. – Tarik Apr 17 '14 at 19:18