On Tuesday, 28 November 2023 at 08:51:21 UTC, Mark Davies wrote:
> I did it this way ...
You always print the full array of bytes this way. Output piped to od -c
is
0000000 1 2 3 4 5 377 377 377 377 377 \n - 1 2 3 4
0000020 5 377 377 377 377 \n
Those 377s are char.init
, 0xFF.
On Tuesday, 28 November 2023 at 09:43:47 UTC, Dom DiSc wrote:
> For a 'long' 10 characters is likely to be not enough (long max is 9223372036854775808 which has 19 chars, and you should reserve additional one for the sign and one for the terminating null), so I would at least recommend using char[21].
Signed max is all bits but the sign bit set, so 7FFF...FFFF, so signed max is always an odd number. d can confirm:
$ rdmd --eval 'writeln(long.max)'
9223372036854775807
$ rdmd --eval 'writeln(2+to!string(long.max).length)'
21
There's no terminating NUL here, which might be an oversight.
> with char[10] your function becomes a big hole in your security, as it can easily be misused to write 10 bytes of freely selectable garbage behind your allocated memory.
This is D though, so without separately disabling bounds checks, there's an error:
core.exception.ArrayIndexError@d1.d(22): index [18] is out of bounds for array of length 10
or with -betterC:
d1: d1.d:21: Assertion `array index out of bounds' failed.
Aborted
Here's a minimal edit to fix the char.init
output:
char[] longToString(long n) @nogc
{
static char[21] x;
size_t length;
ulong power;
x[0] = '-'*(n<0);
long t = (n<0)*-n + (n>0)*n ;
while (n != 0)
{
power++;
n /= 10;
}
length = power;
power -= (x[0] != '-');
while (t > 0)
{
x[power] = (t % 10) + '0';
power--;
t /= 10;
}
return x[0 .. length];
}
As you can see, slices from this longToString are good until the next call to it. The other C-like way to manage memory is to pass in the buffer to use, which in D can be a slice of a static array on the caller's stack. You'll probably have a much better time with manual memory management if you use custom allocators.