On Mon, 24 Jun 2024 10:50:15 -0600, Rob Gardner <robma...@gmail.com> 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.