Hipreme's #5 Tip of the day - Avoid raw pointers at all cost

Hipreme msnmancini at hotmail.com
Fri Nov 11 13:05:19 UTC 2022


Attention, C and C++ programmers are more likely to use what I'm 
going to talk about.

If you're a C++ programmer, you're probably thinking about 
shared/unique pointers. But that's not what this is about.

Take the `void*` type. This type can be pretty much anything, 
this is "okay" if you wanted to make your code more generic, but 
there is a much better way to handle that. Look at that code:

```d
import core.stdc.stdlib;
void* myInt = malloc(int.sizeof);
*(cast(int*)myInt) = 500;
writeln(*(cast(int*)myInt));
free(myInt);
```

This is a code that can be common to happen on C, but you can do 
it a lot better. You can actually make your casting a bit saving 
information about its size, you could do it with a struct, but 
you could also do it with one of the D features: slicing:
```d
import core.stdc.stdlib;
void[] myInt = malloc(int.sizeof)[0..int.sizeof);
```
Now, you will have information saved on how much info is 
allocated on your int by doing `myInt.length`. Which means that 
any attempt to assign data to the pointed location, this location 
will be bound checked.


Another thing I strongly recommend is not using malloc. The first 
reason is that it makes your code harder to read, unsafe, 
untraceable and longer.
If you just use instead:

```d
void[] myInt = new void[int.sizeof];
```

Will basically have the same effect of the code before in terms 
of usage, no import, less to write, traceable code (-profile=gc).

Now, if you need to use that just for the sake of generic data 
and no heap allocation is really needed, I must recall on your 
mind the underused `union` and the underused `std.variant` (aka 
Tagged Union). My own way to use union if you don't need the 
tagged union as you already know how your data flow works, this 
is a pattern that I shall do it from now on (specially because 
you won't be casting your data all the way instead of just using 
`cast(Something*)(voidPointerData)`:


This is an example of my generic audio buffer pool for various 
audio APIs
```d
union HipAudioBuffer
{
     version(OpenAL)
     {
         import openal;
         ALuint al;
     }
     version(OpenSLES)
     {
         import opensles.slinterface;
         SLIBuffer* sli;
     }
     version(XAudio2)
     {
         import directx.xaudio2;
         XAUDIO2_BUFFER* xaudio;
     }
}
```

Then, instead of just casting your data from void*, you can just 
access the "cast" itself as a property.




More information about the Digitalmars-d-learn mailing list