C does have some notion of visibility: put private declarations into the .c file instead of the .h file and declare static linkage. You could have a function that returns a pointer to const for read only data. Obviously they can cast that away, but other languages have unsafe escape hatches too. C also has static analyzers to help with some classes of bugs.
Cowboy code might be common, but you don't have to do that. If using something C-like, C++ definitely gives you a lot more tools to write safe code (or hang yourself, up to you) though.
C has "some notion" of a lot of things. That doesn't make them particularly usable at scale. C has the worst static typing of a language that can even plausibly call itself statically typed in the modern world.
C++ is an option to obtain the sort of thing I talked about, yeah, but in 2023 you need to use something memory safe for something as important as sudo, and C++ on its own is not. C++ and a great static analysis tool would be the minimum I would consider acceptable, but there is something to be said for things like Rust that build the analysis all the way in to the compiler rather than relying on external tools, and then future Rust external tools can build on that even more solid foundation if even more assurance is needed.
Cowboy code might be common, but you don't have to do that. If using something C-like, C++ definitely gives you a lot more tools to write safe code (or hang yourself, up to you) though.