I tend to use features from C89 and nothing else when I write new code. I can write classes and templates (including container templates) with structures and macros and a simple naming convention.
Over the years, I have used C++, and looked at C99 now and again, and I have reached one inescapable conclusion: NEW C variants suck. Used correctly, with well chosen libraries, C89 actually is portable, just like C is advertised to be. The newest C++/C99 stuff tends to always be changing, even in minor variations of the same compiler, let alone across platforms.
Many of the features of C++ and additions to C99, such as 'inline' functions are very handy things. I just don't bother to try to use these 'bleeding edge' features anymore. Function call overhead isn't all that big, and macros can be written to safely handle most things I would otherwise use an 'inline' for.
The problem is, all of these language lawyering pedants out there who try to keep up with the latest fickle hairsplitting of C99 or C++ implementation rules and interpretations compete with each other to make the most 'compliant' version of the language compiler/tools according to the interpretation of changing standards.
I have a lot of Visual C++ code from only a few years back that (without a major overhaul) could not possibly be used on a modern version of the same compiler. I dig up fairly straight forward old code, and it doesn't compile anymore. Somebody made a compiler 'better' by breaking my code!
The nice thing about C89 is, everybody quit bickering over the way it should work years ago, and it isn't changing out from under me. It's easy to understand, clear and simple. I write code, and it compiles under any compiler it's likely to be tried on and even most of the half-baked, buggy 'embedded' compilers without having to 'fix' it.
Of course, visual studio is a problem unto its self. It wants to 'upgrade' older projects from earlier versions such that if you share them, nobody can build it without upgrading to the 'latest' version of Microsoft's bug mill, and subtle incompatibilities seep into the code making older versions of the compiler totally unable to build it, even if you compiled with a batch, makefile or jam. Most recently, I had some std::allocator type stl code that built under gcc and Visual studio.net, yet it broke between one version of .NET and another. Of course, GNU isn't free of such defects. The recent GNU C++ 'offsetof' ban (((class*)(NULL))->member) that generated dire warnings that couldn't be turned off really got under my skin. I never use virtualized class members (functions, yes, but not scalars and compounds), but it insisted I mustn't do this "just in case".
Of course, C++ templates would be nice if I could do everything with them that I could do with the preprocessor. I can't. Wouldn't token pasting and string-izing in a C++ template be nice? Then I get some dimwit who insists that I should use the C++ templates for "everything" instead of the preprocessor. Guess what? You can't do 10% of "everything" that can be done with the C preprocessor using C++ templates, and the C preprocessor code is actually easier to write, read and debug (though you might have to invoke the preprocessor and gnu indent on a few things). It is just unlovely to behold.