This thread honestly irritates me. Most of the people responding here should know better.
Yes, your proposed use of pointers is bad practice. Using unions here is even worse practice.
Do not use unions. They are dangerous. They seem like magic but are filled with peril. They have very strict and almost universally poorly-understood rules that your compiler _will not_ warn you about when you misuse them (and you _will_ misuse them).
Your actual problem is that you're trying to stuff unrelated objects into a single array. This is bad code - for any language, C or otherwise - and the actual fix is to stop doing what you're trying to do. Making one big array with all game objects represented by a single struct is bad design. Don't do it.
Even if you make your code "easy" with the use of unions, your array is still going to be poorly laid in memory. Each game object being as large as the largest object. In other words, if a bullet needs at most 20 bytes and a player object requires 500 bytes, every bullet is still going to take up 500 bytes. Iterating through your bullets (of which you'll have many) will make poor use of the cache because they are not tightly packed.
Using a single base struct for your game objects also mean your game logic is going to be slow. Having only a single array means that during iteration, you must branch for each object depending upon its type in order to execute the appropriate logic. Doing this defeats the branch predictor in the CPU, which is possibly the single most important piece of modern hardware optimization you have available aside from the cache itself.
The efficiency problems are secondary. The _incorrect_ code you're almost guaranteed to write combined with the _sloppy architecture_ you'd be buying into are the real problems.
Use separate arrays. Preferably, break your objects up into components, and put each of those into their own arrays. Do not use unions. Fix your bad architecture rather than trying to paper over it.