Julien Lebot Julien Lebot - 29 days ago 6
C Question

Is C still being widely used in game engines?

The title is a bit of a misnomer, what I mean really is "C with classes".

Let me explain, recently I bought the book ShaderX7 which came with a lite (and old) copy of the Unigine engine for one of the articles about shadow mapping techniques.

I was dabbling through the code when I realized that, while the author was using C++ and inheritance and all the C++ goodness, most if not all the method content was essentially C-style code; for example:

int Shader::get_param(const char *name,char *src,String &dest) const {
char *s = src;
int size = (int)strlen(name);
while(*s) {
if(!strncmp(s,name,size)) {
if((s == src || strchr("\n\r",*(s - 1))) && strchr(" \t",*(s + size))) {
src = s;
s += size;
dest.clear();
while(*s && strchr(" \t",*s)) s++;
while(*s && strchr(" \t\n\r",*s) == NULL) dest += *s++;
if(dest.isEmpty()) {
Log::error("Shader::get_param(): can't get \"%s\" \n",name);
return 0;
}
memmove(src,s,strlen(s) + 1);
return 1;
}
}
s++;
}
return 0;
}


I am not saying this is bad, it does the job and that's what matters but I'm more used to C++ style constructs, with std::string, vectors etc... and I make big use of the Boost libraries; so this kind of style come as a bit of a surprise to me.

Is it really better/faster to use this kind of code than to go the generic, OO way ?

Did I fall into the "too much abstraction" trap ?

Edit: corrected method name to make it clear what it is doing.

Answer

First and foremost I must admit that I'm not a games developer, even though I have developed a fully functional 3D game engine in the past.

That aside, I do have a few words about optimizations, "spoiling" languages and so on.

When developing an application — any application — the golden rule of optimizations is "don't optimize before you make it work." You need to fully support all the functionality you want in your application, and only then you should optimize it. The reasons vary; the most important one is that while you may believe something is "slow," it may not be your bottleneck. You may be spending a lot of time optimizing something that doesn't require optimization. Furthermore, optimizations often blur your code simplicity and maintainability, which may lead to bugs in the near or far future. If this piece of code didn't require optimizations, you've complicated the code for nothing.

While that is the golden rule of optimizations, there is one big exception. When you know in advance that your application will be stressed out to the max, you need to make some different choices in the beginning (in the architecture or in the design phases) and also along the way. Also, the general rule that the platforms are getting better and faster doesn't apply for games, where the competition between the developers is on the very edge of technology. Here are several points to consider:

  1. Some lingual features may be costly. Exceptions in C++ are a good example.
  2. Some lingual features may actually save you code and will cost little or nothing during runtime. C++ templates are a good example, though you still may wind up creating lots of code during compilation, leading to a bigger binary, and therefore lower performance, potentially.
  3. Infrastructures (STL for example) are generic. By making a solution specific to your domain, you MAY be improving your performance. A simple example — if you have a vector that will always be 3 items long, you will definitely be better than the stl::vector implementation. However, this is not always the case. For further reading, see chapter 11 of "Efficient C++" by Dov Bulka. This is an excellent book in general for your question.

In general, using C with classes is a good start for writing fast code while retaining a structured and well-designed project, but one should not neglect the whole of C++ excellent features. More often than not, trying to roll out your own solution to a problem covered by C++ (e.g., polymorphism) will be slower than the out-of-the-box solution, unless you can make the solution VERY specific to the problem at hand.