2

I want to use C with templates on a embedded environment and I wanted to know what is the cost of compiling a C program with a C++ compiler?

I'm interested in knowing if there will be more code than the one the C compiler will generate.

Note that as the program is a C program, is expect to call the C++ compiler without exception and RTTI support.

Thanks, Vicente

Vicente Botet Escriba
  • 4,305
  • 1
  • 25
  • 39

12 Answers12

6

The C++ compiler may take longer to compile the code (since it has to build data structures for overload resolution, it can't know ahead of time that the program doesn't use overloads), but the resulting binary should be quite similar.

Actually, one important optimization difference is that C++ follows strict aliasing rules by default, while C requires the restrict keyword to enable aliasing optimizations. This isn't likely to affect code size much, but it could affect correctness and performance significantly.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
4

There's probably no 'cost', assuming that the two compilers are of equivalent quality. The traditional objection to this is that C++ is much more complex and so it's more likely that a C++ compiler will have bugs in it.

Realistically, this is much less of a problem that it used to be, and I tend to do most of my embedded stuff now as a sort of horrible C/C++ hybrid - taking advantage of stronger typing and easier variable declaration rules, without incurring RTTI or exception handling overheads. If you're taking a given compiler (GCC, etc) and switching it from C to C++ mode, then much of what you have to worry about is common to the two languages anyway.

Will Dean
  • 39,055
  • 11
  • 90
  • 118
  • Thanks for sharing your experience. Have you see a little lost in performances? – Vicente Botet Escriba Mar 22 '11 at 23:53
  • @Vicente: I'm not Will, but can answer the question: We have done this (with GCC-compiled codes), and there has been absolutely no difference in the performance. The generated assembly code is the same. – Brooks Moses Mar 23 '11 at 20:47
2

The only way to really know is for you to try it with the compilers you care about. A quick experiment here on a trivial program shows that the output is the same.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
2

Your program will be linked to the C++ runtime library, not the C one. The C++ is larger as well.

Also, there are a couple of differences between C and C++ (aliases were already pointed out) so it may happen that your C code just does not compile in C++.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
1

If it's C, then you can expect it will be exactly the same.

To elaborate: both C and C++ will forward their parse tree into the same backend that generates code (possibly via another intermediate representation), which means that if the code is functionally identical, the output will look the same (or nearly so).

Templates do "inflate" code, but you would otherwise have to write the same code or use macros to the same effect, so this is no "extra cost". Contrarily, the compiler may be able to optimize templates better in some cases.

Damon
  • 67,688
  • 20
  • 135
  • 185
1

A C++ compiler cannot compile C code. It can only compile C++, including a very ugly language which is the intersection of C and C++ and the worst of both worlds. Some C code will fail to compile at all on a C++ compiler, for example:

char *s = malloc(len+1);

While other C code will be compiled to the wrong thing, for example:

sizeof 'a'
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Well, my intention is to migrate the C source so the compilation pass with the C++ compiler, so I will not have to be reduced to this "very ugly language in the intersection". I expect that I will need to make some adaptation and that the regression will give me enough confidence. – Vicente Botet Escriba Mar 23 '11 at 00:04
1

I have found this extra-ordinary document Technical Report on C++ Performance. I have found there all the answers i was looking for.

Thanks to all that have answered this question.

Vicente Botet Escriba
  • 4,305
  • 1
  • 25
  • 39
0

There will be more code because that is what templates do. They are a stencil for generating (more) code.

Otherwise, you should see no differences between compiling a C program with a C compiler versus compiling with a C++ compiler.

If you don't use any of the extra "features" there should be no difference in size or behavior of the end result.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • 2
    This question appears to be about a C program, i.e. no templates. I think Vicente understands that templates can add code (but not always), and just wants to make sure he isn't starting out from behind. – Ben Voigt Mar 22 '11 at 20:13
  • @Thomas: if the alternative was macro, it won't be worse. – Matthieu M. Mar 22 '11 at 20:14
  • 1
    @Ben Voigt: actually the question is about adding C++ templates to C code. – Matthieu M. Mar 22 '11 at 20:14
  • @Matthieu M.: Comparing C without macros to C with templates, the templates will generate code for each instantiation; thus there will be more code. The OP did not mention anything about macros. – Thomas Matthews Mar 22 '11 at 20:21
  • Of course, my intention is to use templates where I'm forced to use macros in C. I could extend the question on how templates compares to macros at execution time. My believe, is that it should be easier to write templates that can even be more efficient than using macros. – Vicente Botet Escriba Mar 23 '11 at 00:00
  • @Vicente: Templates are much safer than macros. You don't need to do the `do {} while (false);` or similar constructs. – Thomas Matthews Mar 23 '11 at 16:20
  • @Vicente: The question about templates versus macros is an interesting one -- and one worth asking separately, as it's not really the same question as the one here about the same program, and I think the answers will differ. – Brooks Moses Mar 23 '11 at 20:44
0

Although the C code will likely compile to something very similar (assuming there's no exception support enabled), using templates can very rapidly result in large binaries - you have to be careful, because every template instantiation can recursively result in other templates being implicitly instantiated as well.

bdonlan
  • 224,562
  • 31
  • 268
  • 324
  • Yes, I know the implications of templates and I suspect that in an embedded environment we need to take care also of the space, so used them with caution. – Vicente Botet Escriba Mar 23 '11 at 00:07
0

There was a time when the C++ compiler linked in a bunch of C++ stuff even if the program didnt use it and you would see binaries that were 10 to 100 times larger than the C compiler would produce. I think a lot of that has gone away.

old_timer
  • 69,149
  • 8
  • 89
  • 168
0

Since this is tagged "embedded", I assume its for embedded systems?

In that case, the major difference between C and C++ is the way C++ treats structs. All structs will be treated like classes, meaning they will have constructors.

All instances of structs/classes declared at file scope or as static will then have their constructors called before main() is executed, in a similar manner to static initialization, which you already have there no matter C or C++.

All these constructor calls at bootup is a major disadvantage in efficiency for embedded systems, where the code resides in NVM and not in RAM. Just like static initialization, it will create an ugly, undesired workload peak at the start of the program, where values from NVM are copied into the RAM.

There are ways around the static initialization in C/C++: most embedded compilers have an option to disable it. But since that is a non-standard setup, all code using statics would then have to be written so that it never uses any initialization values, but instead sets all static variables in runtime.

But as far as I know, there is no way around calling constructors, without violating the standard.

EDIT: Here is source code executed in one such C++ system, Freescale HCS08 Codewarrior 6.3. This code is injected in the user program after static initialization, but before main() is executed:

static void Call_Constructors(void) {
  int i;
  ...
  i = (int)(_startupData.nofInitBodies - 1);
  while (i >= 0) {
    (&_startupData.initBodies->initFunc)[i]();  /* call C++ constructors */
    i--;
  }
  ...

At the very least, this overhead code must be executed at program startup, no matter how efficient the compiler is at converting constructors into static initializtion.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • This is erroneous, at least for GCC -- it generates exactly the same sequence of instructions for C and C++ programs with a static struct, and does not call a constructor. (I tested and looked at the assembly output.) The simple and trivial way around calling the constructors is to inline them, at which point they go away to nothing. This appears to be what GCC does. – Brooks Moses Mar 23 '11 at 20:41
  • @Brooks What is erroneous? There is no guarantee by any standard that the compiler will optimize away those constructor calls into static initalization. I know of C++ compilers that will not perform such an optimization. What GCC port for an embedded system with NVM did you test this with? If you test it on a desktop computer it will obviously not be an issue. – Lundin Mar 24 '11 at 07:42
  • @Lundin: Admittedly, I didn't check on a non-desktop machine -- but I checked by reading the generated assembly code, not by measuring timing, and the code was exactly the same in both cases -- in particular, there is no loop calling constructors. (Will NVM change its existence, rather than simply where it's copying from?) Thus, what I believe is erroneous is the claim that this *will* happen, not the claim that it *may* happen on *some* compilers. There are many things for which the standard makes no guarantee against inefficient compilers causing ill performance. – Brooks Moses Mar 24 '11 at 15:56
  • 1
    @Lundin I don't see which constructors are you talking off, ass every C type is a POD, so no constructor associated until you define one. – Vicente Botet Escriba Mar 24 '11 at 18:57
  • 1
    @Brooks On a non-NVM machine, the static initialization and constructor calls needn't necessarily occur in runtime. The compiler can make optimizations and prepare the values at compile time, so that everything is already in place when the executable is uploaded from the HD to RAM (though I believe many desktop compilers still do static initialization in runtime?). On a NVM system you cannot do such optimizations as every value used resides in NVM and must be uploaded to RAM during runtime. A majority of the compilers for such systems then execute code like the one I posted. – Lundin Mar 25 '11 at 07:35
  • @Vicente In C++, there will be a default constructor present even if you don't define one. However, I'm not sure whether the default constructor must be there as a mandatory requirement by the standard, or if defining it is up to the compiler implementation. – Lundin Mar 25 '11 at 07:44
  • @Lundin, any POD type, by definition, has a trivial constructor (i.e. it does nothing) so the compiler is free to leave it out. – Dirk Holsopple Aug 13 '12 at 17:02
0

C++ runtime start-up differs slightly from C start-up because it must invoke the constructors for global static objects before main() is called. This call loop is trivial and should not add much.

In the case of C++ code that is also entirely C compilable no static constructors will be present so the loop will not iterate.

In most cases apart from that, you will normally see no significant difference, in C++ you only pay for what you use.

Clifford
  • 88,407
  • 13
  • 85
  • 165