digitalmars.D - Casting arrays
- solidstate1991 (24/24) May 29 2019 For casting arrays in @safe functions between very different
- Dennis (25/38) May 30 2019 Don't do this, that function can not be trusted. For casts of
- solidstate1991 (8/32) May 30 2019 I know. I probably should upgrade the wrapper to filter out
For casting arrays in safe functions between very different
types, I have to write a trusted wrapper that checks if the two
arrays are within boundaries, then returns the requested array
type (or even a single instance with a different one) from the
nested system function, and throws an exception if the cast
would result in an error.
Here's an example of one such wrapper, I probably have to put
them into a separate library instead:
/**
* Safely casts one type of an array to another.
*/
T[] reinterpretCast(T, U)(ref U[] input) trusted{
T[] _reinterpretCast() system{
return cast(T[])(cast(void[])input);
}
if ((U.sizeof * input.length) % T.sizeof == 0){
return _reinterpretCast();
} else {
throw new Exception("Cannot cast safely!");
}
}
The cast to void[] is needed because D often doesn't always let
me to cast directly between types this way ("Cannot implicitly
cast between types..."), especially structs.
May 29 2019
On Thursday, 30 May 2019 at 01:14:57 UTC, solidstate1991 wrote:
/**
* Safely casts one type of an array to another.
*/
T[] reinterpretCast(T, U)(ref U[] input) trusted{
T[] _reinterpretCast() system{
return cast(T[])(cast(void[])input);
}
if ((U.sizeof * input.length) % T.sizeof == 0){
return _reinterpretCast();
} else {
throw new Exception("Cannot cast safely!");
}
}
Don't do this, that function can not be trusted. For casts of
basic types, the compiler already has such runtime checks:
```
int[] a = [3, 4, 5];
auto b = cast(double[]) a;
```
"An array of size 12 does not align on an array of size 8, so
`int` cannot be cast to `double`"
You allowing it for ANY type as long as alignment is okay invites
all kinds of safety violations.
```
void main() safe
{
char*[1] a = [new char('\xCC')];
auto slice = a[];
auto b = reinterpretCast!(int*)(slice);
writefln("%08X", *b[0]);
}
```
https://run.dlang.io/is/QVNlEv
Prints:
743B50CC
The 74 3B 50 are bytes out of bounds. There's more to array
casting than alignment for it to be safe.
May 30 2019
On Thursday, 30 May 2019 at 08:30:14 UTC, Dennis wrote:
Don't do this, that function can not be trusted. For casts of
basic types, the compiler already has such runtime checks:
```
int[] a = [3, 4, 5];
auto b = cast(double[]) a;
```
"An array of size 12 does not align on an array of size 8, so
`int` cannot be cast to `double`"
You allowing it for ANY type as long as alignment is okay
invites all kinds of safety violations.
```
void main() safe
{
char*[1] a = [new char('\xCC')];
auto slice = a[];
auto b = reinterpretCast!(int*)(slice);
writefln("%08X", *b[0]);
}
```
https://run.dlang.io/is/QVNlEv
Prints:
743B50CC
The 74 3B 50 are bytes out of bounds. There's more to array
casting than alignment for it to be safe.
I know. I probably should upgrade the wrapper to filter out
pointer arrays, structs with pointers (or arrays) in them are
also an interesting question. I mainly use it for fast loading of
structs from files rather than painstakingly load each individual
value, also this way I just can put the read or writebuffer to
the checksum calculator, so pointers weren't really an issue for
me.
May 30 2019








solidstate1991 <laszloszeremi outlook.com>