Taking pure to mean referentially transparent, I'm not sure I understand your point here. If you are mutating a statically allocated struct or array passed by reference, doesn't that have a very similar effect to global variables? It makes the dependence explicit rather than implicit which is useful, but it is still effectively global state.
You can't return locally created variables [beyond primitives].
Beyond simple primitive reading/returning functions, you often create some arrays or structs, then pass a pointer to the necessary arrays and structs to your functions, so it can read and write them.
This way the functions can stay pure.