D: Convert/parse uint integer to string. (@nogc)

Julian Fondren julian.fondren at gmail.com
Tue Nov 28 10:36:33 UTC 2023


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 at 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.


More information about the Digitalmars-d-learn mailing list