fbc optimizes string assignment + concatenation, for example:
a = b + c + d assign(a, concat(concat(b, c), d))
becomes:
a = b assign(a, b)
a += c concatassign(a, c)
a += d concatassign(a, d)
If a is a fixed-length string, appending c & d requires determining a's current length, which is done by searching for the null terminator.
The problem is that in case b contained null bytes, the first of those will become a's null terminator, and following string appends will start at the wrong offset.
'' Assigning to dynamic string:
'' dynstr = chr(&hAA) + chr(0) + chr(&hBB)
'' becomes:
'' dynstr = chr(&hAA) AA 00
'' dynstr += chr(0) AA 00 00
'' dynstr += chr(&hBB) AA 00 BB 00 ok.
''
'' Assigning to fixed-length string:
'' fixstr = chr(&hAA) + chr(0) + chr(&hBB)
'' becomes:
'' fixstr = chr(&hAA) AA 00
'' fixstr += chr(0) AA 00 (or maybe AA 00 00, doesn't matter)
'' fixstr += chr(&hBB) AA BB 00 appended at first null,
'' since the real length isn't
'' stored anywhere - visibly
'' different result.
#macro dumpBytes( s, size )
scope
var p = cptr(ubyte ptr, (s))
for i as integer = 0 to (size)-1
print " ";hex( p[i], 2 );
next
print
end scope
#endmacro
print "assigning chr()+chr()+... to STRING :";
dim s as string
s = chr(&hAA) + chr(0) + chr(&hBB) + chr(0) + chr(&hCC)
dumpBytes(strptr(s), len(s)+1)
scope
print "assigning chr()+chr()+... to STRING * N:";
dim s as string * 5
s = chr(&hAA) + chr(0) + chr(&hBB) + chr(0) + chr(&hCC)
dumpBytes(@s, 5+1)
end scope
scope
print "assigning string variable to STRING * N:";
dim fs as string * 5
fs = s
dumpBytes(@fs, 5+1)
end scope
scope
print "assigning chr()+chr()+... to ZSTRING * N:";
dim z as zstring * 5+1
z = chr(&hAA) + chr(0) + chr(&hBB) + chr(0) + chr(&hCC)
dumpBytes(@z, 5+1)
end scope
scope
print "assigning string variable to ZSTRING * N:";
dim z as zstring * 5+1
z = s
dumpBytes(@z, 5+1)
end scope
I.e. the optimization can cause visible differences. This wouldn't happen if the strings were appended in the non-optimized form, because there normal dynamic strings would be used which are capable of handling embedded nulls.