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:
```d
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.