scanf takes an address (pointer) of a value, the format specifier tells what kind of pointer.
scanf("%d", (arr + i) ) means you are giving scanf the address arr plus an offset of i,
when you write *arr = 10; you can also write it as *(arr + 0) = 10; so you are de-referencing the value and assigning it 10 in other words you cannot give this to scanf since it wants a pointer.
so
arr = malloc(10*sizeof(int));
+---+---+---+---+---+---+---+---+---+---+
arr ->|0 | | | | | | | | | 9 |
+---+---+---+---+---+---+---+---+---+---+
arr + i is an address in the range 0..9, de-referencing a value in the array you write *(a+i)
but
arr = malloc(sizeof(int));
+---+
arr ->| |
+---+
writing *arr you are de-referencing the one value you allocated
*arr = 10;
+---+
arr ->| 10|
+---+
however writing
scanf("%d", arr);
is fine since arr is a pointer that points to an integer and scanf takes a pointer.
malloccall. (Of coursearritself is a pointer object, not an array object.)