EmbeddedRelated.com
Forums
The 2026 Embedded Online Conference

validity of ... reasons for preferring C over C++

Started by Nobody October 16, 2014
On Wed, 15 Oct 2014 19:21:11 +0200, Wouter van Ooijen wrote:

> PS I am (in the context of this question) NOT interested in
> - whether a reason is valid (please start a different thread for > discussing this, I'll surely join in).
Okay, then. To start with some comments from the original post:
> - semantic distance to the machine code (I can't easily see what code > this C++ construct will cause)
If you think you know what code a given C construct will generate, you've been out of the loop too long. Modern C compilers can be very aggressive when it comes to optimisation, taking full advantage of the concept of "undefined behaviour", including what used to be obscure cases such as aliasing. If you need the kind of control you get from assembler, you either need to use assembler, or at least look at the actual assembler code the compiler is generating. If you think you know, think again.
> - C++ stronger typing gets in the way (forces you to write lots of casts)
This is an advantage, not a disadvantage. If you're targeting a specific CPU, you don't need to worry about one of the reasons why casts are problematic: the fact that the standard doesn't actually define representation. You can ignore the fact that ... Integers may be big-endian, little-endian, Vax-endian or something else; signed integers may use twos-complement, ones-complement, or sign-bit representation; floats could be just about anything; structures may have padding anywhere other than before the first element; pointers may be simple indices into a flat address space or complex structures involving tags, segments and/or whatever else. You do, however, still need to consider the effects of the cast with respect to C's aliasing rules. The compiler is entitled to assume (with some caveats) that objects with different types do not overlap; modifying one will not affect the other. But casts tend to result in exactly that. And the "entitled to assume" isn't just for language lawyers any more; modern compilers (at least the ones for desktop/server architectures, which are enveloping an increasing proportion of the "embedded" space) do actually take advantage of that freedom.
Nobody schreef op 17-Oct-14 1:00 AM:
> On Wed, 15 Oct 2014 19:21:11 +0200, Wouter van Ooijen wrote: > >> PS I am (in the context of this question) NOT interested in > >> - whether a reason is valid (please start a different thread for >> discussing this, I'll surely join in). > > Okay, then. > > To start with some comments from the original post: > >> - semantic distance to the machine code (I can't easily see what code >> this C++ construct will cause)
or write volatile float x = 1.75; x = sin( x ); for an 8-bit chip. If you really know and understand what code that will generate (or cause to be included) you are a compiler writer. Wouter van Ooijen
On 17/10/14 01:00, Nobody wrote:
> On Wed, 15 Oct 2014 19:21:11 +0200, Wouter van Ooijen wrote: > >> PS I am (in the context of this question) NOT interested in > >> - whether a reason is valid (please start a different thread for >> discussing this, I'll surely join in). > > Okay, then. > > To start with some comments from the original post: > >> - semantic distance to the machine code (I can't easily see what code >> this C++ construct will cause) > > If you think you know what code a given C construct will generate, you've > been out of the loop too long. > > Modern C compilers can be very aggressive when it comes to optimisation, > taking full advantage of the concept of "undefined behaviour", including > what used to be obscure cases such as aliasing. > > If you need the kind of control you get from assembler, you either need to > use assembler, or at least look at the actual assembler code the compiler > is generating. If you think you know, think again. >
It is quite possible to estimate the assembly generating for some types of code in C. If you've got a complex function, or using floating point on an 8-bit micro, or have whole-program optimisation, then the generated assembly is going to be incomprehensible. But for smaller functions or code snippets, it is often easy and helpful to understand the generated assembly, and if it is critical code then it can be good to work with the source until the generated assembly matches your expected assembly structures (or you file a "missed optimisation" bug report - that is part of how compilers improve over time). So I don't know the details of what my compiler will end up producing for large sections of code - but I /do/ know how it works and what it will do for small and important sections. However, /exactly/ the same applies to C++ as to C. It's the same compiler, it works in the same way, and for code where I am interested in the generated assembly, I can work with the tools in the same way. What people seem to think is different about C++ is that "innocent" statements such as defining an instance of a class "A a;" can lead to "hidden" code generation (via constructor calls, etc.), or that an "innocent" statement of "a = b + c" can lead to "hidden" code due to operator overloading. This is clearly nonsense. Nothing is hidden, as you have the source - if you want to know about the constructor, look it up. The equivalent C code would be "A a; initA(&A);", generating similar code. Operator overloads will generate extra code on something like "a = b + c" /if/ the operation requires more code - just like in C (where you would say "matrixAdd(&a, &b, &c);" or whatever). If you don't know what your C++ code is doing, that's /your/ problem, not the language's problem.
On 17/10/14 08:27, David Brown wrote:
> If you don't know what your C++ code is doing, that's /your/ problem, > not the language's problem.
Well yes. But some languages do have more obscured traps that that require higher levels of skill and more continual alertness. The interesting question is always "given circumstances X, is Y or Z the more appropriate language". One of the problems with modern C and C compilers (compared with K&R C) is that their sophistication places far more subtle traps that require language lawyers to understand. When even the language lawyers disagree amongst themselves, that's not a good starting point. K&R C had 228 pages. C Traps and Pitfalls had 228 pages. They were all you needed in the 80. How long are the modern equivalents? So I will assert that nowadays there are fewer circumstances in which C/C++ is the best choice for circumstances X. But I will add two important caveats: carefully-chosen language subsets significantly mitigate the problems, and interoperability with existing code bases dictate the language (the COBOL problem/argument).
On 17/10/14 10:29, Tom Gardner wrote:
> On 17/10/14 08:27, David Brown wrote: >> If you don't know what your C++ code is doing, that's /your/ problem, >> not the language's problem. > > Well yes. But some languages do have more obscured traps that > that require higher levels of skill and more continual alertness. > > The interesting question is always "given circumstances X, is > Y or Z the more appropriate language". > > One of the problems with modern C and C compilers (compared with > K&R C) is that their sophistication places far more subtle traps > that require language lawyers to understand. When even the language > lawyers disagree amongst themselves, that's not a good starting > point.
If you were purely discussing the compilers, then I might partially agree - modern compilers are more advanced and have more optimisations than old tools that were closer to C-to-assembly translators. So there are issues, such as aliasing problems, that can make code that /looks/ correct behave incorrectly with modern tools. Countering that, modern C is a better language - for example, it requires proper function declaration, which eliminates a source of obscure problems in K&R C. And modern tools are far better at static error checking and spotting issues that sailed past unnoticed in the "good old days" - as long as you know how to use your tools, you will write safer code with fewer bugs using modern tools. Yes, there are fine points in the "law" that lead to disagreement amongst the "lawyers". The way to handle this is simple - the same way as it has always been handled, and the same way you suggest below. Avoid using such constructs or language features. The same applies with C++, which has more scope for confusion and complications (such as figuring out exactly which template instantiation will be used). If you are not sure, don't write code that you don't understand.
> > K&R C had 228 pages. C Traps and Pitfalls had 228 pages. They > were all you needed in the 80. How long are the modern equivalents? > > So I will assert that nowadays there are fewer circumstances in > which C/C++ is the best choice for circumstances X.
I disagree, in the embedded world. In PC programming, I agree - very often you are better with a language like Python than with C or C++.
> But I will > add two important caveats: carefully-chosen language subsets > significantly mitigate the problems, and interoperability with > existing code bases dictate the language (the COBOL problem/argument).
Yes (to both).
David Brown <david.brown@hesbynett.no> writes:
> I disagree, in the embedded world. In PC programming, I agree - very > often you are better with a language like Python than with C or C++.
I have to think that even in MCU programming there have to be better alternatives to C or C++. Ada seems like a possibility except that the toolchains are either obscure or very expensive. There have been some C dialects like Cyclone that were clever but never got traction. And I guess there are some specialty EDSL's like Atom that aren't so good for general purpose development. Forth is interesting but it's from a different world, and still unsafe though with fewer traps than C.
On 10/17/2014 11:35 AM, Paul Rubin wrote:
> David Brown <david.brown@hesbynett.no> writes: >> I disagree, in the embedded world. In PC programming, I agree - very >> often you are better with a language like Python than with C or C++. > > I have to think that even in MCU programming there have to be better > alternatives to C or C++. Ada seems like a possibility except that the > toolchains are either obscure or very expensive. There have been some C
I don't know. I think Ada only helps protect against some superficial mistakes. It does nothing to prevent someone from using a poor overall design or conceptual errors that may be much harder to catch.
On 17/10/14 11:35, Paul Rubin wrote:
> David Brown <david.brown@hesbynett.no> writes: >> I disagree, in the embedded world. In PC programming, I agree - very >> often you are better with a language like Python than with C or C++. > > I have to think that even in MCU programming there have to be better > alternatives to C or C++. Ada seems like a possibility except that the > toolchains are either obscure or very expensive. There have been some C > dialects like Cyclone that were clever but never got traction. And I > guess there are some specialty EDSL's like Atom that aren't so good for > general purpose development. Forth is interesting but it's from a > different world, and still unsafe though with fewer traps than C. >
In theory, one could do much better than C or C++ - but not in practice. For some systems, Ada is a possible choice. But while Ada is "safer" than C in some ways, it has its own problems - and the limited choice of tools, and limited number of users, mean that it is only appropriate in certain niches. This applies even more so to other language choices, such as Eiffel.
On 17/10/14 10:19, David Brown wrote:
> On 17/10/14 10:29, Tom Gardner wrote: >> On 17/10/14 08:27, David Brown wrote: >>> If you don't know what your C++ code is doing, that's /your/ problem, >>> not the language's problem. >> >> Well yes. But some languages do have more obscured traps that >> that require higher levels of skill and more continual alertness. >> >> The interesting question is always "given circumstances X, is >> Y or Z the more appropriate language". >> >> One of the problems with modern C and C compilers (compared with >> K&R C) is that their sophistication places far more subtle traps >> that require language lawyers to understand. When even the language >> lawyers disagree amongst themselves, that's not a good starting >> point. > > If you were purely discussing the compilers, then I might partially > agree - modern compilers are more advanced and have more optimisations > than old tools that were closer to C-to-assembly translators. So there > are issues, such as aliasing problems, that can make code that /looks/ > correct behave incorrectly with modern tools. > > Countering that, modern C is a better language - for example, it > requires proper function declaration, which eliminates a source of > obscure problems in K&R C. And modern tools are far better at static > error checking and spotting issues that sailed past unnoticed in the > "good old days" - as long as you know how to use your tools, you will > write safer code with fewer bugs using modern tools.
I agree with all that, but I will note that back in the "good old days" <cough> it was a truism that "cc is only half a compiler; the other half is lint".
> Yes, there are fine points in the "law" that lead to disagreement > amongst the "lawyers". The way to handle this is simple - the same way > as it has always been handled, and the same way you suggest below. > Avoid using such constructs or language features. > > The same applies with C++, which has more scope for confusion and > complications (such as figuring out exactly which template instantiation > will be used). If you are not sure, don't write code that you don't > understand.
Ach! That's a problem in the trenches. Too many people don't know that they don't understand the features. They /think/ they know and so shoot other people in the foot. The only "work-around" for that is to have systems with fewer surprises, and to restrict the use of "dangerous" tools to those that have previously and repeatedly demonstrated that they can use them safely. Not palatable. I've forgotten the name for the generic phenomenon that the ignorant think they are better than they actually are. If anyone can come up with a decent way of allowing people to realise what they don't know, then they have probably found a way of making themselves very famous, rich, and winning all sorts of prizes. One of my few saving graces is that I have some clue what I don't know.
>> K&R C had 228 pages. C Traps and Pitfalls had 228 pages. They >> were all you needed in the 80. How long are the modern equivalents? >> >> So I will assert that nowadays there are fewer circumstances in >> which C/C++ is the best choice for circumstances X. > > I disagree, in the embedded world. In PC programming, I agree - very > often you are better with a language like Python than with C or C++.
Agreed, but I'd like to have a good reason to take a hard look at Lua.
>> But I will >> add two important caveats: carefully-chosen language subsets >> significantly mitigate the problems, and interoperability with >> existing code bases dictate the language (the COBOL problem/argument). > Yes (to both).
On 17/10/14 10:35, Paul Rubin wrote:
>Forth is interesting but it's from a > different world, and still unsafe though with fewer traps than C.
That's actually quite a strong point in Forth's favour.
The 2026 Embedded Online Conference