When using scanf for arrays, it seem that the function works fine whether I use '&' operator or not.
"Seems" being the operative word.
Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
If you call scanf as
scanf( "%s", s );
the expression s is converted from type "100-element array of char" (char [100]) to "pointer to char" (char *) and its value is the address of the first element of the array (&s[0]).
If you call scanf as
scanf( “%s”, &s );
s is the operand of unary &, so the conversion doesn’t occur, and the expression &s has type "pointer to 100-element array of char" (char (*)[100]). This is a problem, since the %s conversion specifier expects an argument of type char *. Passing an argument of any other type results in undefined behavior - the operation may work as expected, or it may crash outright, or it may corrupt data, or it may leave the program in a bad state such that it crashes later, etc.
Both expressions s and &s resolve to the same value - the address of an array is the same as the address of its first element - but their types are different, and in C different pointer types may have different representations (IOW, the way the address value is stored for a char * may be different from the way an address value is stored for a char (*)[100]). So
scanf( "%s", &s );
could fail on some platforms.
My exact question is when I use &ch(while ch is string) do we create double pointer?
No. If ch is declared as char ch, then &ch has type char *. If ch is declared as char ch[N], then &ch has type char (*)[N].