How well does GCC support C++ for the attiny85 as I am looking at converting over to C++?
GCC support for C++
This link will give some information on AVR GCC C++: http://www.nongnu.org/avr-libc/u...
C++ in an ATtiny? Kinda like using a Caterpillar D7 to dig a hole in a flower pot, isn't it?
Keep in mind that there are very few resources in an ATtiny, especially SRAM. You can blow through 512 bytes pretty fast, especially if you do much dynamic allocation of objects and use lots of classes.
Don't get me wrong, I happen to like C++. Even so, as my metaphor above shows, I also believe in using the right tool for the job. C++ in an ATmega2560 - sure! In an ATtiny85 -- I wouldn't.
Stu
There is no penalty to using C++ over C when used properly. So if you're willing to use C on the ATtiny, then there is no reason not to use C++.
(it's a myth that C++ causes bloat)
There is no penalty to using C++ over C when used properly.
- Writing your own "new"
- Allocating static objects in flash
- Exceptions: Just Say No
- Large virtual function tables, dynamic allocation of objects, and tiny memories.
- The STL and your ATtiny - why "free" code isn't free.
Stu
(Paraphrasing Lee) "I'll bite, Stu":
C++ in an ATtiny? Kinda like using a Caterpillar D7 to dig a hole in a flower pot, isn't it?
If you (as you yourself admit) do not know what to use and what to not use in C++ when programming for microcontrollers, from where comes this certainty that it is a Caterpillar in a flower pot?
especially if you [...] use lots of classes
This points to a huge misconception. Could you tell me how much you loose using classes (many or few, don't care) compare with not using classes, given that you do not use virtual functions? (Hint, the "this-pointer").
BTW, while you're at it, I'd like to have some hint about the cost of actually using virtual functions (some indication of the space used for the v-table data-structure, and what the indirections during the call would be).
Kewl! We have at least two C++ experts on the AVR! Where's the tutorial? :twisted:
As for the huge number of classes, I had intended to say with virtual functions. Sorry, I tend to assume that use of lots of classes implies virtual functions, since that's where (I consider) the power of C++ shows up. Obviously you don't need to use virtual functions and without them the v-tables are downright frugal. Without virtual functions, object size is now limited to the member data and the single indirect v-table of reasonable size. You are then limited only by the size of the ATtiny, just as you would be in straight C.
On the other hand, you didn't respond to the questions about exceptions, redefining the new operator, static allocation of objects in flash, etc.
Oh, and BTW, everything I've seen from Joerg and Eric suggest that C++ is not "officially" supported on the AVR, although that may be my interpretation, not fact.
Where's the tutorial?
Stu
Edit 1: I seem to recall a thread on allocation of the vtable to flash. That would go a long way to ameliorating any heap usage of objects, since I believe the vtables for any class would be static, wouldn't it?
How well does GCC support C++ for the attiny85 as I am looking at converting over to C++?
The key phrase here is "when used properly".
As for the huge number of classes, I had intended to say with virtual functions. Sorry, I tend to assume that use of lots of classes implies virtual functions, since that's where (I consider) the power of C++ shows up. Obviously you don't need to use virtual functions and without them the v-tables are downright frugal. Without virtual functions, object size is now limited to the member data and the single indirect v-table of reasonable size. You are then limited only by the size of the ATtiny, just as you would be in straight C.
Indeed virtual functions are a powerful feature, however they come at a cost. There is still a lot of power in encapsulation, and the other paridigm differencees that c++ brings to the table. So while it may not be any better than using pure C, my point is that it's not any worse either.
Oh, and BTW, everything I've seen from Joerg and Eric suggest that C++ is not "officially" supported on the AVR, although that may be my interpretation, not fact.
Yes, it's my understanding that the GCC C++ implementation for AVR still has some holes. My comments were general C++ comments, not specific to GCC/AVR support of it.
Kewl! We have at least two C++ experts on the AVR! Where's the tutorial? :twisted:
Sorry, no tutorial, I'm no "expert".. perhaps someday. As I said, my comments were general in nature, only to disband the myth that C++ instantly adds bloat to the application.
The C++ compiler is available for the AVR. However there are caveats in using it, and I'm sure there are undiscovered issues. I know that the list of known GCC bugs also covers some C++ bugs for the AVR. Joerg and I generally don't look at the C++ issues as neither of us have enough knowledge in the matter. Also because there are still bugs in the C toolchain that need to get fixed. We certainly welcome more help in the C++ area.
I seem to recall a thread on allocation of the vtable to flash. That would go a long way to ameliorating any heap usage of objects, since I believe the vtables for any class would be static, wouldn't it?
These got rid of the link errors. When you need these, what they are for? Haven't had time to look into it.
extern "C" void __cxa_pure_virtual(); extern "C" void __cxa_guard_acquire(); extern "C" void __cxa_guard_release(); void __cxa_pure_virtual() { abort(); } void __cxa_guard_acquire() { } void __cxa_guard_release() { }
Use malloc/free inside the news and deletes. Do a search, we've seen this posted several times.
You should become a politician, Stu :wink: You are dodging the burden of proof for the Caterpillar by asking for a tutorial...
What did I react to? This: A sweeping allegation that there is a heavy run-time performance penalty for using C++ in embedded systems, backed by no facts whatsoever.
Re the tutorial, I am not planning on writing any such thing - at last not right now (see footnote though). If I was to write it, it might go something like this (sketch):
Getting C++ to work (ie. getting the compiler up).
OO programming basically stands on the tiers: Encapsulation, Inheritance and Polymorphism. You don't need to use all three tiers, but if you do you should be aware of the costs.
ENCAPSULATION is inheretly good. It helps depict things in a natural way. You ask objectys to operate rather than call functions to manipulate data. Encapsulation will also help you avoid name clashes (as every class is a namespace). This argument is a lot about source code quality and source code eficciency (in the sense that you can maintain well written source code more efficiently).
There is very little run-time performance penalty for using encapsulation. [A few experiments with the "this"-pointer are needed here]. Function calls are resolved at link time, just as in C - there is no overhead for the call per se compared to plain old C.
[Maybe a section here about "all static classes". It would go something like this:
Using classes generally means that you define a class and then instantiate several objects. What if you want to encapsulate eg a piece of hardware that actually only exists in one instance (eg. the ADC)? One elaborate solution is to use a design pattern called Singleton, but then you'd have to pay the penalty of dynamic memory allocation. One alternative is to make all methods of the class static, and then be cautious to not create several object instances of this class]
INHERITANCE: Just as with encapsulation there is no inherent penalty using inheritance compared with plain old C. Apart from the obvious use of inheritance to model specialization/generalization, there is one very interesting use of this in C++ - specifying interfaces.
[Specifying interfaces means creating pure virtual classes, which in turn generates v-table entries, and indirections at call time. the cost in space and time would need to be investigated]
POLYMORPHISM: This implies virtual functions, which in turn generates v-tables... [see above].
Having dealts with the three tiers, we need to cover some other stuff too:
DYNAMIC MEMORY ALLOCATION: An explanation of the costs involved, and why dynamic memory allocation is not always a good idea. Not C++ specific at all, but would still be needed in such a tutorial.
THE COPY CONSTRUCTOR: An explanation of what the copy constructor is, and why we want to avoid activating it. Hide it, and pass objects as reference parameters.
[There was a lot more in my brain whan I started typing but it got lost. I'll come back and edit when recall occurs].
[EDIT]Added: An investigation on any memory penalties regarding the startup code when using C++.[/EDIT]
So Stu, with that embryo for a tutorial done, would you please give at least a hint about your Caterpillar reasoning? 8)
[footnote: Strange coincidence - just the other day I got involved in things pertaining to "C++ on embedded systems" at work, and just the type of questions we are discussing. Spooky. So no tutorial "right now", but who knows...]
So Stu, with that embryo for a tutorial done, would you please give at least a hint about your Caterpillar reasoning? 8)
The problem as I saw it when I made the comment (and I'm sorry it pushed your buttons, Johan) was an assumption of what the OP was assuming would be available to him. As I say below, my initial reaction to C++ code is, "That's needlessly complex and out of touch with the hardware running it." It's unfair, and I know it. My bad.
To be honest and fair, there's no reason why C++ in all its glory should not be available, other than AVR gcc is a volunteer project and no one (myself included) has volunteered to make it complete. That's not a slam on the hard-working supporters of our current toolset (Joerg, Dmitry, Eric, et. al.) but on people like me who should at least contribute something. Mea Culpa.
In fact, C++ is not any harder than straight C in an ATtiny. On the other hand, it's not necessarily any easier. The same issues confront the designer, and I was wrong for implying any different.
As Bjarne Stroustrup himself has said:
I never saw a project for which C was better than C++ for any reason but the lack of a good C++ compiler.
I guess in my mind, C is a small screwdriver while C++ is a power screwdriver - both drive screws into walls, but it's sometimes easier to strip the screw with the power tool.
Another problem I have is that I have dealt with programmers who literally do not want to know about the hardware they're running on. In an embedded environment especially, I believe that attitude to be dangerous and, ultimately, self-defeating. Since those programmers were great advocates of C++ as well, they (unfairly) were linked in my mind. Ehh, what should I be worried about -- they're probably on to Ruby or Python or whatever the next Language To End All Languages(tm) is. :twisted:
In conclusion, I apologize to those who took offense at my desire for a quick humorous phrase (a personality flaw, I admit, along with being long-winded). On the other hand, right now, the answer to "What is GCC support for C++ on AVR" is "well... it's like this..."
Oh, and thanks for the tutorial outline, Johan. Food for thought...
Stu
Edit 1: Stu's Observation On Computer Languages: As long as there are CS Grad Students, there will be new computer languages.
I guess in my mind, C is a small screwdriver while C++ is a power screwdriver - both drive screws into walls, but it's sometimes easier to strip the screw with the power tool.
I guess in my mind, C is a small screwdriver while C++ is a power screwdriver
C: http://www.toolsforworkingwood.c... "These marking knives are both elegant and functional".
C++: http://www.joshspear.com/item/gi... "It is the biggest mofo of a Swiss Army Knife ever invented, ..."
Lee
http://www.joshspear.com/item/gi... "It is the biggest mofo of a Swiss Army Knife ever invented, ..."
Stu
Here is a challange for the C++-evangelists.
"I never saw a project for which C was better than C++ for any reason but the lack of a good C++ compiler."
Is avr-gcc in reality the type of C++-compiler that actually is better than C on a real target?
Or will the evangelist not even a come up with a working C++ example?
class complex { public: int im; int re; complex add(complex a, complex b); } complex complex::add(complex a, complex b); struct complex { int re; int im; }; complex add(complex a, complex b);
Rules of engagement:
Implement the add method and add function.
Initialise a and b, calculate c = (a + b) from main (one project using C and the other C++).
Both projects shall compile on the same optimisation level on the highest warninglevel without warnings.
Output: resulting size of BSS, TEXT and DATA and segments for the two projects and two working projects with linker scripts, make files and source.
Note:
The code may not be optimised away by the compiler some meaningful code must be generated.
Surely the optimiser will always optimise a menaingless piece of code like c=(a+b) unless either (a) 'c' is volatile or (b) 'c' is subsequently used somewhere (probably being written out to a 'volatile' PORT or something)
This is the problem with test code like this - far better to set a test like "flash a 1Hz LED" or something (ie the "real" kind of work that microcontrollers actually get used for)
Here is a challange for the C++-evangelists.
Quote:"I never saw a project for which C was better than C++ for any reason but the lack of a good C++ compiler."
Is avr-gcc in reality the type of C++-compiler that actually is better than C on a real target?
Or will the evangelist not even a come up with a working C++ example?
A reason for not using C++ would be the expertise of one's programmers.
Or will the evangelist not even a come up with a working C++ example?
I might, in due time. (As has been hinted at in my "New toy!"-thread in the OT forum I might become involved in some work re exactly this topic. Unfortunately for this community this work will be baset on the TI MSP430 microcontroller, but if I find the time I might just do some parallell AVR experiments.)
Still, you're not aiming at the dead center of my point. Your argument seems to be very similar to the classic "compiler wars", where a certain piece of code shall be compiled with the contending compilers to show which one is best.
I hope that I have argued two points above:
My first point is that you can use C++ to get good quality code, where "quality" definitively is not restricted to fastest and/or smallest generated code. In my opinion (and experience) there are other aspects of code quality, eg. clearness (as in "easy to use in a code inspection or walkthrough"), readability (as in "stands a better chance of being maintained with reasonable cost" etc.
My second point is that there are a number of misconceptions as of the costs of using C++. One such misconception is goes something like "as soon as you write something in C++ there is a huge overhead due to the v-table things".
I certainly never had the intention to argue that C++ should be used "to the limit" (exploiting all C++ constructs), in all cases, for all problems etc. (I have not even argued that you must choose one or the other for a certain project. Last time I looked, and the umphteen times before that it was quite possible to mix C and C++ in one project, just as it is possible to mix C and assembler. The latter is being done - whats so strange about the former?
Some of the arguments here (and in other similar threads) remind me a lot of the usual arguments in discussions on C vs. assembler, and IMO those arguments often tend to be more or less ridicolous, eg. "black-and-white" arguments where you must choose one side and then stick to it no matter what. Please let's not do that here.
While it is easy to play at C++, it isn't really easy to make the mental transition from C procedural methods to truly understating and fully exploiting the object oriented aspects of C++.
I don't think the issue should be 'is C smaller' but is it worth climbing the learning curve to really know what you are doing with C++ when you are writing relatively simple programs for small microcontrollers.
Learning C++ makes a lot of sense when you are are part of a team designing a set-top box using an ARM processor, but it is IMHO way overkill for using on an AVR for controlling a microwave oven. I agree with the Caterpillar D7 Bulldozer for a flowerpot analogy.
I would love to see that tutorial though.
Smiley
P.S. I believe that any idiot can (an many idiots do) write decent programs in C. But that it is much harder to write a 'decent' program in either Assembler or C++, both of which IMHO are far harder to use properly.
But that it is much harder to write a 'decent' program in either Assembler or C++, both of which IMHO are far harder to use properly.
C++ being harder because it has significantly more abstractions than C
Obviously you need to restrict the usage of the language capabilities (polymorphism, exceptions, dynamic casts...what more?) in order to use it for coding on a resource constraint target. Maybe a fair part of C++ remains, I don't know.
But I do know one thing. If not even the simplest example of a compiled program using a class will show up, nor will all those other examples where C++ might prove it self do.
My example was deliberately chosen not to "stress" the compiler in any way. It demonstrates encapsulation, which in its own is a nice feature. I strongly believe that the best way to put the bloating discussion to rest is to actually show a working example which for obvious reasons need to be comparable to C. And if the experts can't provide that example I might chose to reject all those other claims they make.
Olof
C++ offers several tools for abstraction in addition to those of C. But is design by objects any more abstract than design by functions?
If by "design" you mean the thinking of programmer during the writing of the program, then one can interpret that several ways. You can have a C++ programmer who knows the language and his compiler well. As he writes the C++ code, he is already visually the resulting assembly code. So, while his has tools of abstraction, he may be designing considering mostly the resulting assembly language. Whereas one can have a C programmer who doesn't even understand a data or return-call stack, doesn't know assembly language, and is thinking of his program only in C constructs. So, in their "design", one could argue the C++ programmer be designing at a lower level of abstraction than the C programmer while using language with greater amounts of abstraction.
Yes, learning to think in objects can be a hard and not-so-fast process. At least it was (and still is) for me. I find this strange but interesting. When I act in "real life" many (most?) things are OO rather than functional.
Eg when I'm about to drive somewhere I do engine.Start() rather than Start(engine). There is no general procedure Start that can act on everything. The operation Start is one of the "aspects" of the engine. And the wipers. But certainly not the doors. They have an Open operation, which the wipers does not have. (The engine might have an Open operation but it is reserved for the mechanic..., and engine-opening is conceptually quite different from door-opening.)
So the question is, if "real life" things often are so naturally OO, why was/is it so hard for me to think like that when programming? In the end, what I manipulate in my programs are in the end "real world" things (lets leave the "We're all a computer simulation" thing out for now :wink: .)
It demonstrates encapsulation, which in its own is a nice feature.
Agreed on the nice feature (understatement, if you ask me)!
On the "challenge application/example": One way to force the compiler to actually generate code without resorting to some strange trick would be to read the real and imaginary parts of the complex numbers from ports, and output the result to pins. No need to construct something that really would work, just read 2x2x2 bytes from PORTB for the real and imaginary parts of the two complex inputs, do the computation, and output 2x2 bytes for the result. This should force the compiler to actually generate code, right? (Or am I just in need of sleep?)
This now has become more tempting than I had planned. Might just let the MSP430 rest a while tomorrow, and try this out... No promises, though.
As he writes the C++ code, he is already visually the resulting assembly code. So, while his has tools of abstraction, he may be designing considering mostly the resulting assembly language. Whereas one can have a C programmer who doesn't even understand a data or return-call stack, doesn't know assembly language, and is thinking of his program only in C constructs. So, in their "design", one could argue the C++ programmer be designing at a lower level of abstraction than the C programmer while using language with greater amounts of abstraction.
I'm missing something here: What forces the C++ programmer to think more in/on the generated machine code than the C programmer?
Learning C++ makes a lot of sense when you are are part of a team
IMO, learning C++ (or maybe some other OO language) makes a lot of sense when you are working on your own. Roumor has it that you have been programming in C# - on your own... 8)
Learning to do it "differently" is usually unpleasant, especially with age. After several years of religious adherence to top-down design, I read Meyer's classic on OOD and fell in love instantly (with OO not the author!). But I was about 23 years old.
I'm not on either side here as I believe that the premise of 'better' is not absolute. There is a separation of arguments really...
1. does either C or C++ produce 'better' code? This could, notionally, be tested once you establish the metric(s) to be used (code size, speed of execution, etc) and an actual benchmark set of requirements (what is the code supposed to do). BUT this is not really possible because - there are many ways of coding anything other than trivial examples, the compiler has a myriad of options that may/not effect the result, there may be a dependency on the compiler used, and there are likely to be cases where using one language has advantages over the other an vice versa.
2. There are qualities to consider that go beyond the raw machine code/space-requirements. There are also all the quality attributes such as: testability, maintainability, reusability, extensibility, portability, etc. These, like space/speed, are things that have to be traded-off.
3. The tool is only really as 'good' as the person wielding it. It is probably fair to say that a 'good' programmer in either language will produce better results than a poor programmer in the other.
Personally, I select the tools in my kitbag that "I think" fit the job at hand, which might not be the same selection as someone else. It is a reflection of my own skill with each, my experience, and any outside constraints placed on me (back to those quality attributes... e.g. if you want something quick then you are likely to get it coded in the language with which I am most familiar).
So, I'm firmly rooted bang in the 'third way'... horses for courses :)
As for the learning curve for OO. Yes it is likely to be steep - if you have been taught procedural programming first! When OO first came into vogue I knew that if I started with C++ all I'd produce would be C with classes (look at the early MS foray into C++... lots of classes that were basically just glorified structures). To avoid this I learned smalltalk first there was no way of me slipping back to my familiar C practices.
P.S. The first language I learned to programme in was an assembler for an olivetti machine that probably had less processing power than the calculators that they now give away in boxes of cereal :)
I'm missing something here: What forces the C++ programmer to think more in/on the generated machine code than the C programmer?
Of course, one of the signs of abstraction is that the resulting assembly language looks less and less like the original source code. When I write a program in Perl, I have little idea about what machine instructions the program will be executing compared to programming in C.
The idea of software design is not all that ambiguous.
We are discussing the advantages of two relatively distinct design approaches, object oriented and procedural (top-down, structured, Yourdon, etc). Again, I question your assertion that design by objects is somehow more abstract and therefore more difficult to learn and use.
We are discussing the advantages of two relatively distinct design approaches, object oriented and procedural (top-down, structured, Yourdon, etc). Again, I question your assertion that design by objects is somehow more abstract and therefore more difficult to learn and use.
C++ being harder because it has significantly more abstractions than C which can lead to choosing a poor overall model or using constructs which are quite inefficient for the task
Further explaining my statement in the context of your point is that with more abstractive power, one has more choices in design. Thus, it can lead to some poorer code than when one has a less expressive language (like C) where there is less choice to choose a construct. With a more abstract language, more things are handled for the programmer so one is further removed from the resultant binary. If one doesn't give careful thought, one can employ abstractions where the compiler generates fairly inefficient results (compared to optimal results). Whereas in a a less abstract language, when you have to do more of the work that an abstraction encapsulates, it would visible if you are choosing an inefficiency.
C++ being harder....
With a more abstract language
kmr wrote:Since you weren't specific enough I had to assume you meant C++ is harder to use and/or harder to learn to use well. Otherwise, what did you mean by "harder"?C++ being harder....
...which can lead to choosing a poor overall model or using constructs which are quite inefficient for the task
it is much harder to write a 'decent' program in either Assembler or C++, both of which IMHO are far harder to use properly.
I'd say C++ is more expressive rather than more abstract.
what did you mean by "harder"?
I believe we are using different definitions of "abstraction".
With a more abstract language
Without quoting prior posts or Wikipedia can you explain how C++ is "harder"?
Before the specifics, here's a few references to books on the subject of using C++ effectively. And again, many of these tips are non-obvious (as anyone would guess from the title word "Gotchas" below).
Effective C++: http://www.amazon.com/Effective-...
More Effective C++: http://www.amazon.com/More-Effec... (as if the first 50 tips weren't enough to cover the language!)
C++ Gotchas: http://www.informit.com/store/pr... ("C++ Gotchas is the professional programmer's guide to avoiding and correcting ninety-nine of the most common, destructive, and interesting C++ design and programming errors. It also serves as an inside look at the more subtle C++ features and programming techniques. This book discusses basic errors present in almost all C++ code, as well as complex mistakes in syntax, preprocessing, conversions, initialization, memory and resource management, polymorphism, class design, and hierarchy design.")
http://profcon.com/profcon/Gotch... ("Production C++ programming is complicated by numerous features of the language that behave or interact in unexpected ways - the Gotchas. Gotchas may cost programmers additional development time to track down obscure bugs, or result in superficially correct code that executes inefficiently. Gotchas appear in all parts of the language. ... Gotchas affect the correctness, efficiency and portability of C++ software.")
Below is a single example that may (or may not) cause an unexpected error -- this is beyond the unexpected inefficiences in my original claim. I present this as single example of where C++ is "harder".
This example is from http://www.linuxdevcenter.com/pu...
const SimpleString& examine_string(const SimpleString& input) { //... maybe do some processing here ... return input; //If "input" refers to a temporary //object, that object will be //destroyed as soon as this //function returns. }
On the surface, this seems like all a fine thing to do, but the above comments state the potential unexpected occurrance. The explanation for the above is: "The C++ compiler is allowed to create an unnamed temporary object for any const reference parameter. After all, you promise not to change the parameter when you declare it const. Unfortunately, the unnamed temporary goes out of scope as soon as control leaves the function, so if you return a const reference parameter by const reference, a dangling reference can result."
If you really want more specific examples, I can supply them once I get back to my references materials. (I haven't used C++ much in the last 5 years, so my memory of the specifics is not precise enough for posting).
I was referring not to abstraction, but to your use of the word abstract:
kmr wrote:With a more abstract language
I don't want to give the impression that I don't like C++. In fact, I do -- quite a lot. For my Computed Tomography simulator, the port to C++ was a big win in terms of segmentation, maintainability, readability, and code reuse. I consider C a high-level assembler and C++ as an extension providing both more abstraction as well as the ability to still predict the emitted assembly code when one needs maximal performance. However, C++ needs to be more carefully used to avoid unexpected consequences.
Edit: Here's some CTSim screenshots: http://www.ctsim.org/screenshots
Thanks. Food for thought.
However, C++ needs to be more carefully used to avoid unexpected consequences.
OK, I'll bite.
The example given is as bad, wrong and dangerous as the C function:
char *examine_string( char *s) { if (s && *s) return s; return "Error"; }
And I've seen variations of this function a LOT.
I personally don't think that C++ is more difficult than C. The problem is that it isn't taught. Most people learn C and then they get a 2 day introduction into C++ and that's it. Koenig and Moo have shown that C++ can be learnt quite efficiently and easily (Accelerated C++) if you focus on C++, and not on C.
The books and websites from Meyers and Sutter are really good (highly recommended). But again, I'm not quite sure if they are appropriate. They focus mostly on advanced usage of C++, and if they were C books, they would have probably been called "Advanced C++ Tips & Tricks".
If the number of publications of what you should do and shouldn't do in a programming language is any indication about its dangerousness the world should have stopped programming in C in the early 80's.
C++ wasn't really designed to be an embedded programming language. I think that becomes quite clear when you look at the footprint of basic_string. I'm not even talking about the STL. But if you ignore the libraries for now and just look at the core language it offers enough features and advantages over C to justify its use on any processor (at least for me it does).
For me the difference between using C and C++ is like the difference in using hand-tools and power-tools (no pun intended). Most of the time I just want the job to get done and I use power tools. But every now and then there is a delicate piece and I need finer control over what is going on, so I revert to hand tools.
And by "reverting" I don't mean that in a bad sense. Granted, working with hand tools is less efficient (time wise), but that is not as important as precision in these cases (think critical timing).
I think this is where most of the "code bloat" in C++ comes from (and don't kid yourself, it exists). It's not that the language produces bloated code, it's the programmer who adds more features because it is so much simpler. In C you might think "no, I would have to add this function, write that one for this structure ... I don't think I'll need it that desparately", whereas in C++ it might be "hey, if I make that one a template I can do that too". Quite simple, isn't it, but you've just doubled your code base of that functional unit.
Markus
Edit: put code into code format and made sample more meaningful
In (almost) every holy war on C++ versus C, on embedded systems, I never see mentioned EC++
If C++ could be used that easy on embedded targets, you should inform the ISO SC22/WG21 committee they're totally wrong.
Likewise, tell firms like IAR and Green Hills that their EC++ compliance is useless, and they wasted a lot of money. :P
~ Lou
Besides function pointers and the CPP as tools of obfuscation, the chaotic nature of procedural designs leads to deterioration as requirements and code change.
Still, my opinion is that such issues with C are more clear when writing or reading C sources compared with C++ where issues exist that would only be known by having knowledge of subtle aspects of the specification and which appear surprising to many when analyzing the source code.
My previous example was not arcane. Wow, passing a constant reference of an object sounds great and safe, taking advantage of C++ features. No worries about pointers dereferencing and "safer" because the object is const. However, many functions like to pass their input argument as their output argument to chain calls [like foo(input_for_both).bar()]. So, many people would think it'd be safe for a function to return the same const reference of an object that the function received. According to the C++ specification, that may or not return a dangling pointer. So what seems ordinary and safe and C++ double-plus good is truly an potential error that may show up at any time.
I'd be surprised if a feature-disabled language ever really takes off. Generally, adding features is good, taking away features is annoying. EC++ probably looked good on paper, but ultimately the answer is probably, no thanks. (For me anyways.)
My previous example was not arcane.
The example is a nit pick, pointing out an obscure anomaly such as those always found in programming languages. You seem to be thereby ignoring the larger more significant issue of software design, by which I mean the principles guiding the structure of elements that comprise the solution.
And, yes, I have been ignoring the very important issue you mentioned. While I could easy make many posts about the positive points of C++ and the wins it has over C, that discussion is really outside the point of my reply to Smiley's comment.
On the "challenge application/example": One way to force the compiler to actually generate code without resorting to some strange trick would be to read the real and imaginary parts of the complex numbers from ports, and output the result to pins.
I had hoped that declaring c as volatile or static both in the C and C++ example would result in working code. And if this would not work it was why I chose to declare the attributes as public (thus violating ecapsulation). This way it would be easy to access them without the need for accessor methods. Which might punish C++ unfair in the simple example. The problem of initialising a and b is also solved here.
I have been thinking about the add method prototype.
complex& complex::add(complex&)
might have been more fair to C++. If anyone cares to try to meet the challange feel free to try that instead.
Anyway the challange is not really about C++ vs. C in general. It's about the compiler maturity regarding C++ in avr-gcc.
I had hoped that declaring c as volatile or static both in the C and C++ example would result in working code.
Probably, but then we are changing the environments in the test, maybe "moving away from the realistic".
But that it is much harder to write a 'decent' program in either Assembler or C++, both of which IMHO are far harder to use properly.
I agree with that statement, Smiley. .... C++ being harder because....
Also, I didn't say it was harder to use.
C++...can lead to choosing a poor overall model
So your argument went from "poor models" to presenting pitfalls of passing by reference (which BTW is a relatively mundane feature of C++). The conflict between C and C++ is procedural design versus object oriented design. Period. The latter is more concrete IMO, not abstract, and therefore more intuitive and easier to use.
But, if you want to take this back to the beginning, very well. Yes, object oriented design is more abstractive -- that was my initial point. I realize my point was misunderstood because I used the word abstract rather than abstractive. I stand by my initial intent, though. Greater levels of abstraction can lead to unexpective inefficiences and choice of a poor model. The first because your source code is further removed from the resulting binary and it's easier to choose a construct that will use more machine cycles than optimal whereas in a language of lower abstraction you'd have to explicit code all those cycles. That'd give you a hint there could be a more efficient method when you realize you're writing hundreds of lines of code for something that should be simpler. That's similiar to clinical medicine. If you write a medication order and the nurse has to draw up 10 ampules of a medication, that's a simple (however non-precise and not always accurate) sign you chose the wrong medicine or dose. As for the second point, simply when you have a greater number of abstractions to choose from, you have a greater chance of choosing a less than optimal abstraction then when you have less abstractions to choose from.
I realize you are pointing our advantages of C++. You're preaching to the choir. As I mentioned I like C++ very much and its object oriented paradigm can be highly effective. If you search for threads on AVRFreaks you'll see where I was stating the improvements of C++ over C, even for embedded applications. It's not being schizophrenic, but examining the multiple issues from multiple perspectives.
Personally, my favorite programming language (and the large majority of my open-source source code) is in ANSI Common Lisp which transcends object-oriented programming into what is collectively termed the "metaobject protocol" -- a much higher level of abstraction than the simple object-oriented nature of languages like C++ and Java.
Despite the great advantages of abstractiveness, as one person wrote metaphorically earlier in this thread, "it's sometimes easier to strip the screw with the power tool." This is more true in the context of coding for microcontrollers with scare resources than for systems with more cpu speed and system storage. And, that was the whole context for this thread.
Edit:
1. By concrete, I assume you mean that the programming construct more closely resembles a physical object. Yes, I agree. That "concreteness" comes from the abstraction that C++ provides. Indeed, that's usual basic introdution into object-oriented programming. The elementry text starts with some simple physical object like "vehicle" which is subclassed into "4-wheel motorized vehicle" and splits into "car" and "truck" subclasses.
2. As examples of trying to choose the best abstraction: the choice of subclassing an object versus adding attributes to an subclass versus employing multiple inheritance versus adding an object as a member of an object; deciding to make a function a method of an object or creating a new object which performs the function on an input argument of the original object; using inline functions (space/time tradeoffs); and splitting an larger object into subjects. While it is great to have these choices, there can be significant benefit to optimially choosing amongst these possibilities. With C, you simply don't have these constructs to choose amongst. With assembly, you have even less constructs to choose amongst.
I have appended a reference implementation that works as intended (tested with cygwin).
Interesting is the (deviously hidden) need for a copy and assignment operator. Though the same kind of compiler support is needed in the C example too.
I have also tested the C++ implementation (without printf, no optimisation) using Code Warrior for a HC908 target. Resulting in:
Summary of section sizes per section type: READ_ONLY (R): 163 (dec: 355) READ_WRITE (R/W): 30 (dec: 48) NO_INIT (N/I): 48 (dec: 72)
Attachment(s):
I'm not quite sure how to plan to use the C++ challenge. But, for C, wouldn't the standard idiom for efficiency is to pass pointers to the objects rather than the objects themselves. Your C++ code does that by passing references (which are pointers to the objects) rather the objects themselves.