2

So I know that pointers are variables that store the address(s) of some other variables. But the thing that I am confused with is this: I know that using the name of the array in most of the contexts would decay it to the base address of the element. But I get confused here: When we declare an array say int arr[5], and then say scanf("%d",arr+1), here arr is an address right? We did not explicitly store it in any variable i.e, a pointer. So how does arr+1 arithmetic work similar to pointer arithmetic? Also this: *(arr+1) would give us the value in the address arr+1. I do realize that we can dereference an address, but here I kind of find it difficult to work with it because I kind of lose the "hey this pointer points to this address.." here. And my final question would be, is this the exact way that we can differentiate an address from a random value in a computer? Like arr+1 leads to the address of the next integer in this case, and not normal +1 (pointer arithmetic basically).

I hope that my question does not have any ambiguity.

Floatoss
  • 130
  • 5
  • in your `scanf` example, yes, `arr` decays to a pointer to the first element in the array. The array is `int`, so it decays to an `int*`. Therefore, `arr+1` performs pointer arithmetic, which points to the 2nd element in the array. In the `*(arr+1)` context, the `*` means dereference, so that gives the value of the 2nd element in the array. `*(arr+i)` is equivalent to bracket notation, `arr[i]`, and in the case of arrays, bracket notation is preferred. – yano May 10 '22 at 14:42
  • Related: [What is array to pointer decay?](https://stackoverflow.com/q/1461432/12149471) – Andreas Wenzel May 10 '22 at 14:49
  • `arr+1` is a pointer *expression*, (basically: `pointer+offset`). Pointers need not be stored; they can be just expressions, just like numbers. – wildplasser May 10 '22 at 14:59
  • If I say `int n = 5; printf("%d\n", n + 1);` it prints `6`. But where did that 6 get stored? It was never in a variable, either. – Steve Summit May 10 '22 at 15:04

2 Answers2

3

Your problem starts with this misunderstanding:

So I know that pointers are variables that store the address(s) of some other variables.

"Pointer" is a type category. There are values of pointer types, which are also referred to as "addresses", and there also variables declared to hold such values. This is entirely analogous to there being values of type int and variables declared to hold int values. Also, just as we might refer to either an int value or an int variable as "an int", people can and do refer to both pointer values and pointer variables as "pointers".

Additionally, it is a bit imprecise and a bit misleading to say that pointer values are the addresses of variables. They are the addresses of objects, and although in-scope variables do represent objects, not all objects correspond to variables.

When we declare an array say int arr[5], and then say scanf("%d",arr+1), here arr is an address right?

When the scanf call is evaluated, the array value of arr is automatically converted to a pointer value, the address of the first array element.

We did not explicitly store it in any variable i.e, a pointer.

You do not need to store a pointer value in a variable in order to use it in an expression. In fact, just the opposite: if you want to use the value of a pointer variable in an arithmetic expression, you must first read the value from it -- a process called "lvalue conversion". The same applies to variables of all types and expressions involving most operators. Most operations are defined in terms of values, and variables are just one way to convey those.

So how does arr+1 arithmetic work similar to pointer arithmetic?

There is no "similar to" here. It is pointer arithmetic. arr is automatically converted to a pointer value. That value is a suitable operand for the addition operator, provided that the other operand is of integer type. This is a pointer arithmetic expression.

Also this: *(arr+1) would give us the value in the address arr+1.

Yes, though it would be more idiomatic to say the value at address arr+1.

I do realize that we can dereference an address, but here I kind of find it difficult to work with it because I kind of lose the "hey this pointer points to this address.."

Well, most people would write *(arr+1) as arr[1], which is 100% equivalent, but easier to read and usually clearer. Other than that, I'm not sure what you're asking, if anything.

is this the exact way that we can differentiate an address from a random value in a computer? Like arr+1 leads to the address of the next integer in this case, and not normal +1 (pointer arithmetic basically).

How a C program interprets a given sequence of bytes is determined by the data type it attributes to the sequence. That is exactly the function of data typing. There is no difference discernable in the underlying physical memory, it is all a manner of the program's interpretation. x+1 is pointer arithmetic if x has pointer type, including as the result of automatic conversion from an array. It is integer addition if x has type int, long, etc.. It is floating-point addition if x has type double, float, or long double.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thank you for your reply. "They are the addresses of objects..", I do not know what objects are in C. About the Pointers being a type category, it does make sense. So if I understand properly now, Pointers are types that _hold_ addresses. Similar to how `int` holds an integer. Now I always presumed that if I said `int* ptr=arr`, only then I would be allowed to do pointer arithmetic on `ptr.` So now it makes sense because `arr` is a pointer value (an address), and hence we can perform the arithmetic. All we need is a pointer value. – Floatoss May 12 '22 at 01:26
  • About the last thing, say if I said `int a=123456`, and you happened to print it in hexadecimal. Let's say we also have an address similar to that, and now when I do `+1` to both of them, it is a valid way to check if one is an address or just a normal integer is what I meant, but yeah it is clarified. – Floatoss May 12 '22 at 01:27
2

Let's suppose we have:

int n = 1;
int arr[100];
  • arr + n: yes this is an address.
  • arr + n: yes, we do doing pointer arithmetic here.
  • arr + n is the same thing as &arr[n].
  • *(arr + n) is the same thing as arr[n].

Example of pointer arithmetic:

Let's suppose the size of an int is 4 bytes and arr is the address 0x10000:

  • arr + n is 0x10000 + n * 4
  • sor for example arr+2 is the address 0x10008

Your last question is somewhat unclear but if you understood the above it should be clear.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115