This is documented in the "Arithmetic Evaluation" section of the
manual, about 3/4 of the way through:
An _expression_ of the form '##X' where X is any character sequence such
as 'a', '^A', or '\M-\C-x' gives the value of this character and an
_expression_ of the form '#NAME' gives the value of the first character of
the contents of the parameter NAME. Character values are according to
the character set used in the current locale; for multibyte character
handling the option MULTIBYTE must be set. Note that this form is
different from '$#NAME', a standard parameter substitution which gives
the length of the parameter NAME. '#\' is accepted instead of '##', but
its use is deprecated.
Note that the
## form does work fine in conjunction with parameter expansion:
$ msg=hello
$ for (( i=1; i <= $#msg; ++i )); do echo $(( ##$msg[i] )); done
104
101
108
108
111
But that's not particularly efficient.