On Mon, 24 Jun 2024 10:50:15 -0600, Rob Gardner <[email protected]> wrote:
[reformatted]
> $ readarray -d ' ' X <<< "A B C"
This does not remove the separator, so X[0] ends up containing "A ", X[1]
contains "B ", and X[2] contains "C\n" (as there was no trailing
space to terminate the string).
See:
$ declare -p X
declare -a X=([0]="A " [1]="B " [2]=$'C\n')
> $ ./printarg ${X[0]}A
> 65 0 65 $
You are not quoting the expansion. This means that your C code is receiving
TWO arguments, namely "A" and "A". Remember that in C, strings are
NUL-terminated. While you only print argv[1], you're printing too many
characters (you go up until n+2), so your code ends up printing 65 (the
first "A"), 0 (the string terminator), and 65 again (the second "A", which
presumably is contiguous in memory).
So your code is printing 0 simply because in C, strings are NUL-terminated
and you're reading that NUL and one character past it. Nothing to do wth
bash.
For completeness, if you quote the expansion, you get (at least on my
system):
$ ./printarg "${X[0]}A"
65 32 65 0 83
That is, "A", a space, and "A" again (which is the result of the quoted
expansion), 0 for the string terminator, and a random 83 which is
whatever follows in memory (strangely, it seems to be 83 consistently
though). Again, nothing to do with bash.
> $ read -d ' ' -a Y <<< "A B C"
This only reads "A" into Y. Without quotes, the result is the same as in
the first example, except that Y[0] contains "A", not "A ", so when the
expansion takes place, the two "A"'s are concatenated and the C code sees
"AA".
$ declare -p Y
declare -a Y=([0]="A")
$ ./printarg ${Y[0]}A # or "${Y[0]}A", here there's no difference
65 65 0 83
> $ readarray -td ' ' Z <<< "A B C"
This produces
$ declare -p Z
declare -a Z=([0]="A" [1]="B" [2]=$'C\n')
> $ ./printarg ${Z[0]}A
> 65 65 0 83 $
This is again correct given all the above. The only issue I see is that
your C code is reading too many characters from the string it's given.
--
D.