C is a pass-by-value language. If you were to write:
int x;
scanf("%d", x);
scanf would have no idea where to put the scanned result - you need to pass it a pointer to a memory location in which to store the scanned value:
scanf("%d", &x);
You could also make an explicit pointer variable, if that helps you to understand it:
int *y = &x;
scanf("%d", y);
Conversely, printf doesn't care where the value is located, just what the value happens to be. So passing the value:
printf("%d", x);
is just fine. As to your specific questions (assuming int var;):
What is the difference between printf("%d",&var) and printf("%d",var)
Strictly speaking, the first causes undefined behaviour and the second one prints the value of var. In practice, a lot of implementations will print the address of var in the first case.
What is the difference between printf("%p",&var) and printf("%p",var)
This case is just the opposite. The first one prints the address of var, and the second causes undefined behaviour. In practice, it will probably print the value of var, but you shouldn't rely on that. To be really correct, the first one should be printf("%p", (void *)&var);, too, but I've never seen an implementation where what you have written there wouldn't work fine.
printfdoesn't know about the variable's name, it just gets a copy of the value.scanfneeds to store a value, so it must know where.printf("%d", 2 * 3);There's no variable at all!