Eric DayThoughts, code, and other oddments. |
Dark | Light |
|
|
|
< Open Source Cloud || Drizzle, Gearman, and memcached Meetings > C vs C++August 11th, 2009Linux vs FreeBSD, vi vs emacs, MySQL vs PostgreSQL, your habit or favorite technology vs another’s. At the end of the day there is no winner, just a matter of preference for the task at hand. I learned C++ 13 years ago, I forgot most of my C++ knowledge 10 years ago, I discouraged the use of C++ in this period in between, and in the past year I’ve been re-learning C++ (mostly due to Drizzle). So what did I use after unlearning C++ 10 years ago? I wrote everything in C (and by everything I mean this was my performance programming language of choice). This worked quite well, but it’s an interesting evolution that I think is now coming full circle. When I first started programming C, it was a bit clumsy, and I look back at my old code and cringe. I began to develop a certain programming style that can best be described as object-oriented C programming due to the conventions used. The structs, functions that operated on those structs, and types all were nicely separated into abstract objects. Of course C provides little protection so a user could still poke at what they wanted, but the idea was there and things worked well if you stayed in your sandbox. As projects became more complex, my C code needed things like inheritance, polymorphism, and templates (although I did not recognize them under those names as I do now). How do you manage such construct in C? There are a few tricks, one being to make your first struct member be a struct of a base class, and cast up/down when switching context. Another trick is to abuse C macros to give you either shared class methods or polymorphism. For example:
#define HASH_ADD(__hash, __key, __obj, __prefix) { \
if (__hash ## _hash[__key] != NULL) \
__hash ## _hash[__key]->__prefix ## prev= __obj; \
__obj->__prefix ## next= __hash ## _hash[__key]; \
__obj->__prefix ## prev= NULL; \
__hash ## _hash[__key]= __obj; \
__hash ## _count++; \
}
This C macro will take any object with the correct data members and treat it like a hash table. There are a few other related macros to manage other hash table operations. I have a similar collection for lists, queues, and other custom objects. Now, the seasoned C++ programmer will look at these tricks as just say “you’ve created a hacked up limited version of C++ that most people will cringe at”, and I’m starting to agree. It’s time to stop fighting the inevitable. This style of C programming worked very well for me mostly because I was one of just a small handful of programmers that ever looked at this code (most of it never made it open source sadly). Now that I’m working on open source projects and working with developers of all levels, I’m starting to see the value in more common structure and code protections to allow more people to participate easily. A fresh new C++/Java programmer out of college can understand and extend an abstract C++ plugin class more more easy then they can figure out my C macro/casting constructs and work within that framework. Even some experienced C programmers have to take a minute to figure out what I was actually doing (not saying what I was doing was advanced or anything, just more convoluted). C++ classes scale better than custom C preprocessor macro “languages”. By “scale” I mean ease of developer understanding and use. Ever look at the Zend/PHP header files? So, what does this mean? I’m starting to understand the value C++ brings, especially in code organization and compile time guarantees. You still get that raw performance if you are careful and test new containers/libraries (for example, stack in the STL does not perform all that well compared to a raw array or even vector). Lately I’ve been working on a few micro (and not so micro) benchmarks seeing what the difference is between C and C++. There is a small price to pay if you start going crazy with inheritance because each new layer adds some constructor/destructor overhead. I avoided this in C by having large objects with everything (and just used casting or macros). Real inheritance makes code much more readable and extensible though. Three years ago I never would have thought I’d be writing such a blog post, but here I am. This new decision will start trickling into projects I already work in, and new projects will be in C++ if appropriate. Some things will remain i C, but any modular server or application development will probably get switched. I am going to be extremely cautious about performance and will do my best to ensure the move to C++ is not too costly. Are you offended by this? I’d love to hear your thoughts. Also, think of it this way: at least I didn’t say I’m starting to use Java. :) (Sorry to you Java programmers, I’m just trying to stir up trouble) Posted in Drizzle, Gearman, Main, MySQL13 Responses to "C vs C++"
Leave a Reply< Open Source Cloud || Drizzle, Gearman, and memcached Meetings > |
Blog Wiki About Resume RSS Comments Launchpad identi.ca OpenStack Scale Stack Gearman NW Veg Veg Food & Fit |
|
Copyright (C) Eric Day - eday@oddments.org All content licensed under the Creative Commons Attribution 3.0 License. Hosted by Rackspace Cloud |
|
If the choice is between C++ and a C programming style that involves frequent use of macros like that, then I would probably choose C++ (grudgingly). But I personally find little need for complex macros in the C code that I write or admire (e.g. Postgres uses only a handful of non-trivial macros in 400 KLOC of code). I rarely find the need for complex inheritance hierarchies, for example.
Certainly C is going to be more verbose and laborious than C++. But given the advantages in simplicity, portability and ubiquity that writing systems software in C yields, I don’t wish for C++ very often.