0

I've got two questions, really. The first has to do with the interaction between a pointer and a variable, and the second has to do with the interaction between a pointer and an array. What is the best way to understand this?

I understand that a pointer contains the address to a variable, but I'm not sure what the difference is between setting the pointer to an address and setting the pointer to a variable.

I seem to have the same problem with an array, except more complex because an array may not just have one value.

For instance:

int num = 5;
int * p;

p = num;  //This results in an error
p = # //This does not

Whereas:

int num[2] = {5, 10};

p = num;  //This does not result in an error
p = # //This does

For the first situation, I get an error saying, "a value of type "int" cannot be assigned to an entity of type "int *"".

For the second situation, I get an error saying, "a value of type "int (*)[2]" cannot be assigned to an entity of type "int *"".

Why is this?

EDIT: I don't believe this to be a duplicate question. Array decaying does not answer my question at all, and instead this has to do with pointer types rather than properties of arrays. This question has been answered well already, but I would like to clarify that my issue was not answered by anything having to do with array decaying.

  • 1
    See a question about [array decay](https://stackoverflow.com/questions/1461432/what-is-array-decaying) – 1201ProgramAlarm Jul 08 '19 at 01:20
  • To compare apples with apples, the second case should have `int(*p)[2]`, not `int *p`. That is the type of the address of `num`. Then you would get the same pattern of error/non-error. – M.M Jul 08 '19 at 02:34
  • The difference is that 'a pointer set to a value' is a contradiction in terms. – user207421 Jul 08 '19 at 03:20
  • 1
    I consider that the identified duplicate is not actually a duplicate. Array "decaying" is only one factor of several that is relevant to this question. – Peter Jul 08 '19 at 06:11

2 Answers2

1

A variable has a number of distinct properties.

Given your variable definition, which I quote here

int num = 5;

its type is int, its name is num, it is initialised with a value of 5, and its address (e.g. location in machine memory) is &num.

If I was to define a second variable immediately after

int q = 5

then this variable would (like num) have type int, and value 5, but a different name q and a different address in memory &q. Even though they have the same value, the addresses of num and q are different. That (among other things) ensures that assigning q = 6 does not change the value of num.

It goes further. The pointer in your sample

int * p;

means that p is a pointer to an int. It has type int *, so its value can be the address of an int. So the assignment

p = num;  //This results in an error

doesn't work, because p has type int * and num has type int. The two types are distinct, and an int cannot be converted implicitly to an int *, so the assignment is not allowed. They are different types. In the real world, the street address of a house is something different from a house, even if there is an association between them.

However your assignment

p = # //This does not

works, because p is of type int * and &num is the address of an int so also has type int *.

However, with arrays, the rules are a little different.

int num[2] = {5, 10};

p = num;  //This does not result in an error   
p = # //This does

Firstly, num is an array of two int. It has name num, but its type is int[2], and its value is actually based on the pair of ints 5 and 10.

When used in an expression, num is converted to a pointer to its first element. So

p = num;

is equivalent to

p = &num[0];

The conversion of num to &num[0] is called an "array to pointer" conversion.

The second assignment you tried

p = # //This does 

is different. In this case &num is the address of the array num, not the address of its first element. So &num has type int (*)[2] which (in C++) syntactically means "pointer to an array of two int".

The type of p is int * (because that's how you defined it) whereas &num gies a result with type int (*)[2]. Those types are different, so the assignment is invalid.

If you want a variable that points to an array of two int (as distinct from your p which can point at the first element of an array of int) then define

int num[2] = {5,10};
int (*q)[2];       //  q has type int (*)[2]

q = num;      // this will work

Then you can do, for example;

std::cout << (*q)[0] << ' ' << (*q)[1] << '\n';

to print the values 5 and 10. This works because q points at the array, *q is (a reference to) the array num, so (*q)[0] and (*q)[1] access num[0] and num[1] respectively.

Note that the parentheses () are critical in all of the above discussion. *q[0] is actually (by rules of operator precedence and associativity) equivalent to *(q[0]) which is something quite different from (*q)[0]. I'll leave working out what *(q[0]) is (or is not) an exercise.

Peter
  • 35,646
  • 4
  • 32
  • 74
0

Pointers are a big hurdle to come across for new programmers. Let me try to put it in the most easiest way I can.

Pointers are a data type in languages like C and C++ which point to a specific "memory location" specified by the pointer's type, meaning only a int pointer can point to a int memory location.

In your first example,

p = num

gives an error because you are trying to point the pointer to a value, but pointers cannot point to values but instead only memory locations. That is why

p = &num 

works.

In your second example,

p = num

works because for arrays and structs in c and c++, setting the pointer directly to them automatically points to the first memory address specified by the array. Arrays are not special data types by themselves but rather sequences of values right after one another in memory. But,

     p = &num

doesn't work because you are trying to point to the memory location of a memory location. num already points to the first location in the array, and &num points to the memory location of that location. That is why it's an error. Hope you got it!

Emalp
  • 123
  • 7