The difference here is that
char *s = "Hello world";
will place Hello world in the read-only parts of the memory and making s a pointer to that, making any writing operation on this memory illegal. While doing:
char s = "Hello world";
puts the literal string in read-only memory and copies the string to newly allocated memory on the stack. Making
s = 'J';
The char array example does not necessarily place the string on the stack - if it appears at file level, it will probably be in some kind of initialised data segment instead.
First off, in function arguments, they are exactly equivalent:
void foo(char *x);
void foo(char x); // exactly the same in all respects (note! this only applies if the brackets are empty)
In other contexts, char * allocates a pointer, while char  allocates an array.
Where does the string go in the former case, you ask? The compiler secretly allocates a static anonymous array to hold the string literal. So:
char *x = "Foo";
// is approximately equivalent to:
static const char __secret_anonymous_array = "Foo";
char *x = (char *) __secret_anonymous_array;
Note that you must not ever attempt to modify the contents of this anonymous array via this pointer; the effects are undefined (often meaning a crash):
x = 'O'; // BAD. DON'T DO THIS.
Using the array syntax directly allocates it into new memory. Thus modification is safe:
char x = "Foo";
x = 'O'; // No problem.
However the array only lives as long as its containing scope, so if you do this in a function, don't return or leak a pointer to this array - make a copy instead with strdup() or similar. If the array is allocated in global scope, of course, no problem.
The first one is array the other is pointer.
The array declaration "char a;" requests that space for six characters be set aside, to be known by the name "a." That is, there is a location named "a" at which six characters can sit. The pointer declaration "char *p;" on the other hand, requests a place which holds a pointer. The pointer is to be known by the name "p," and can point to any char (or contiguous array of chars) anywhere.
char a = "hello"; char *p = "world";
would result in data structures which could be represented like this:
It is important to realize that a reference like x generates different code depending on whether x is an array or a pointer. Given the declarations above, when the compiler sees the expression a, it emits code to start at the location "a," move three past it, and fetch the character there. When it sees the expression p, it emits code to start at the location "p," fetch the pointer value there, add three to the pointer, and finally fetch the character pointed to. In the example above, both a and p happen to be the character 'l', but the compiler gets there differently.