An array name, or any expression of array type, is implicitly converted to a pointer to the array's first element unless it's either:
- The operand of a unary &(address-of) expression (which yields the address of the whole array, not of its first element -- same memory address, different type); or
- The operand of a sizeofoperator (sizeof arryields the size of the array, not the size of a pointer); or
- The operand of an _Alignofoperator (_Alignof arryields the alignment of the array, not the alignment of a pointer); or
- A string literal in an initializer that's used to initialize an arrary object.
_Alignof is new in C2011.
(The conversion is often referred to as a "decaying".)
None of these apply here, so arr++ tries to increment a pointer object. The problem is, there is no pointer object, just a pointer value. arr, after it decays to a pointer value, is not an lvalue, which means it cannot appear on the left side of an assignment or as the operand of ++.
Similarly, given:
int x;
the expression x is an lvalue, so you can write x = 42; -- but the expression (x + 1) is not an lvalue, so you can't write (x + 1) = 42;.  You can assign to x because it refers to an object.  (x+1) doesn't refer to an object, so there's nothing to assign to.  arr, after it decays, doesn't refer to an object either (you have an array object, but there's no pointer object).
(Your use of arr != arr + 4 should have been a clue; that can never be true.)
Rather than this:
char arr[] = {'a', 'b', 'c', 'd'};
for (; arr != arr + 4; arr++) {
    printf("%c", *arr);
}
you can write this:
char arr[] = {'a', 'b', 'c', 'd'};
char *ptr;
for (ptr = arr; ptr != arr + 4; ptr++) {
    printf("%c", &ptr);
}
Incidentally, at the top of your program, you should change this:
main()
to this:
#include <stdio.h>
int main(void)
Also, run, do not walk, to the comp.lang.c FAQ and read section 6, "Arrays and pointers".