What issues can I expect compiling C code with a C++ compiler?
I've done something like this once. The main source of problems was that C++ is more strict about types, as you suspected. You'll have to add casts where void* are mixed with pointers of other types. Like allocating memory:
Foo *foo;
foo = malloc(sizeof(*foo));
The above is typical C code, but it'll need a cast in C++:
Foo *foo;
foo = (Foo*)malloc(sizeof(*foo));
There are new reserved words in C++, such as "class", "and", "bool", "catch", "delete", "explicit", "mutable", "namespace", "new", "operator", "or", "private", "protected", "friend", etc. These cannot be used as variable names, for example.
The above are probably the most common problems when you compile old C code with a C++ compiler. For a complete list of incompatibilities, see Incompatibilities Between ISO C and ISO C++.
You also ask about name mangling. In absence of extern "C" wrappers, the C++ compiler will mangle the symbols. It's not a problem as long as you use only a C++ compiler, and don't rely on dlsym() or something like that to pull symbols from libraries.
See Incompatibilities between ISO C and ISO C++ for a very detailed list of all of the incompatibilities. There are a lot of subtle issues, including some which don't immediately manifest in a compiler error. For example, one issue that can be a problem is the size of character constants:
// In C, prints 4. In C++, prints 1
printf("%d\n", sizeof('A'));
If I don't wrap all my C files in "extern C { ... }", am I going to get name-mangling where I least expect it?
It bites you when you try to link together C and C++.
I've written a lot of header files containing:
#ifdef __cplusplus
extern "C" {
#endif
// rest of file
#ifdef __cplusplus
}
#endif
After a while it merges into the existing multiple-include boilerplate and you stop seeing it. But you do have to be careful where you put it - usually it belongs after any includes your header does.
Is there some reason why I really shouldn't do this?
If you know for sure you aren't going to combine C and C++ then there's no reason to do it that I know of. But with the gradual migration you describe, it's essential for anything with a published interface that both C components and C++ components need to use.
The big reason not to do it is that it prevents you from overloading functions (at least, in those headers). You might find you want to do that once you've migrated all your code to C++ and started maintaining/refactoring/extending it.