Видимо я чего-то не понимаю
Я думаю, что arr это поинтер на первую ячейку int массива, а сам же поинтер где-то должен хранится
Почему его адрес совпадает с адресом первой ячекйки int массива?
И почему при разыменовывании одного и того же адреса два разных результата?:
Вот как раз в этом и разница. Массив это почти как настоящий указатель, только память под указатель не выделяется и про реальный адрес знает только компилятор. Для удобства в некоторых случаях имя массива ведет себя как указатель, а в некоторых как массив. Возможно, это и не так удобно на самом деле и только вводит в заблуждение.
Четвертый пример вообще сносит неподготовленную крышу и вроде как противоречит примерам выше :) Это результат натягивания массива на указатель.
Адрес автоматического массива берется как смещение относительно указателя стека, так же как и адреса других автоматических переменных.
В общем не стоит относится к массиву как к указателю. Нужно знать нюансы в поведении и использовать там где это необходимо. К слову в реальности не так уж часто приходится иметь дело со статическими/автоматическими массивами, гораздо чаще - с динамическими. И обычно, там где приходится работать со статическими/автоматическими массивами работа эта достаточно тривиальна, без вот этих ваших вывертов мозга :)
Еще один пример подобного не совсем стандартного поведения это имя функции:
Массивы и указатели в C все же не совсем одно и то же. Пожалуй, просто дам ссылку на SO (там даже выдержка из стандарта приведена).
Грубо говоря, переменные типа "массив" не всегда ведут себя идентично переменным типа "указатель на первый элемент массива". В частности, во всем известной конструкции:
int arr[32] = {...};
size_t N = sizeof(arr) / sizeof(arr[0]);