Use & to get the address of an object.
Which of these makes sense?
scanf("%d", ... needs an address of an int as the next argument.
&n is an int *. Good
int n;
scanf("%d", &n);
arr is an int *. Good.
int *arr = malloc(1 * sizeof(*arr));
scanf("%d", arr);
arr[i] is an int: Bad
int *arr = malloc(n * sizeof(*arr));
for(i = 0; i < n; i++)
scanf("%d", arr[i]); // bad
&arr[i] is an int *: Good
int *arr = malloc(n * sizeof(*arr));
for(i = 0; i < n; i++)
scanf("%d", &arr[i]);
&arr[i] is an int *: Good
int arr[5];
for(i = 0; i < 5; i++)
scanf("%d", &arr[i]);
arr is an "array 1 of int". Because it is an array, when passed to a function, arr is converted to the address of its first element. This is an int *: Good
int arr[1];
scanf("%d", arr);
&arr is the address of an "array 1 of int". Although this has the same value as &arr[0], it is not an int *: Bad
int arr[1];
scanf("%d", &arr); // Bad
Result scanf("%d", ... needs an int * argument.
When the modifiable object being passed converts to an int, an & is needed.
When the object being passed converts to an int *, no & is needed.