C++ for the Embedded Programmer - Page 1
Forum section: electronics / general

author: EEVblog
author_rank: Unknown
timestamp: February 23, 2018, 03:27:10 am
content: David Ledger shows some advantages of using C++ in embedded microcontroller applications.The use of template classes and meta programming to make code more platform independent and readable (and fun!) (David made me add that last bit).

author: jeremy
author_rank: Super Contributor
timestamp: February 23, 2018, 04:08:42 am
content: Been doing this for a while now. I’ve heard it called “C+”, essentially meaning that you use only a chunk of the features available.Features I do use:- classes, abstract classes, singletons- pass by reference- single inheritance- templates- namespacesFeatures I don’t use- template metaprogramming (I don’t use this *ever*, anyway)- new- exceptions (sometimes)An excellent library is ETL. It gives you statically allocated versions of the stuff in the STL.

author: Ash
author_rank: Regular Contributor
timestamp: February 23, 2018, 07:24:06 am
content: +1 for ETL - its great. (https://www.etlcpp.com/)I'm a big fan of using C++ features that prevent (or at least make it obvious) you are doing something wrong.A good example of this is explicitly defining array types for buffers with specific sizes. I also prefer references over pointers where I can because you have to work hard to make them "null".For instance:Code:#include <cstdint>static constexpr int BUFFER_LENGTH = 200;typedef uint8_t(&BufferReference);void DoSomething(BufferReference buffer){buffer[BUFFER_LENGTH-1] = 0;// safe, compiler errors on wrong size buffer}uint8_t badBuffer;uint8_t goodBuffer;int main(){DoSomething(badBuffer);// ERRORDoSomething(goodBuffer);// OKreturn 0;}The other really good thing to get your head around is const - tell the compiler when something shouldn't be allowed to be modified and it will prevent you accidentally doing it (and it can often make really good optimisations).I also like doing templates and typedefs for peripherals. When setup right, I can for instance have a GPIO Pin, timer or DMA channel and change instance being used in a piece of code by simply altering a single typedef. the actual template behind can be specialised on instance number and be completely static and basically optimises away into the appropriate register read/writes.. But that's a bit more tricky. However debugging templates is a bitch for the most part.. They can result in some horrific error messages, but the compilers are getting better..The problem with C++ is that you need to have a relatively modern compiler on your platform to take advantages of the good stuff (C++11/14/17).Ash.

author: Fungus
author_rank: Super Contributor
timestamp: February 23, 2018, 11:24:14 am
content: Oh, FFS...C++ is not Python

author: Nusa
author_rank: Super Contributor
timestamp: February 23, 2018, 12:09:38 pm
content: The syntax is:while (expression) statementA single statement without braces is perfectly correct C++ code, even if it offends your personal sense of style.

author: gmb42
author_rank: Frequent Contributor
timestamp: February 23, 2018, 01:21:48 pm
content: Quote from: Nusa on February 23, 2018, 12:09:38 pmAnd not adding braces will inevitably lead to a bug later on in the maintenance cycle. Just add them from the start.

author: NivagSwerdna
author_rank: Super Contributor
timestamp: February 23, 2018, 02:03:08 pm
content: I spy with my little eye AP3513Ehttps://www.diodes.com/assets/Datasheets/AP3513E.pdf

author: crispus
author_rank: Regular Contributor
timestamp: February 23, 2018, 02:33:43 pm
content: The title and the presentation might lead to a war between those who use C++ and those who don't.Personally I think this is mistitled. C doesn't mean SThorribleHAL, so it is not fair to put equality between a poorly written library and a language.As an example, you can look at the ChibiOS STM32 HAL which is absolutely amazing. Here is anexample:Code:while (true) {palSetPad(GPIOD, GPIOD_LED3); /* Orange. */osDelay(500);palClearPad(GPIOD, GPIOD_LED3); /* Orange. */osDelay(500);}Quote from: gmb42 on February 23, 2018, 01:21:48 pmIt is a good practice to add braces, but it doesn't lead inevitably to a bug. But it might.DISCLAIMER: I use C++ in almost all of my embedded (as in Cortex-Mx) projects for more than 5 years.

author: Fungus
author_rank: Super Contributor
timestamp: February 23, 2018, 04:44:53 pm
content: Quote from: Nusa on February 23, 2018, 12:09:38 pmYes, butonlybecause it was correct C code back in the 1970s and breaking existing C code was deemed unacceptable when C++ was being developed.

author: Craftplorer
author_rank: Contributor
timestamp: February 23, 2018, 05:07:49 pm
content: Quote from: crispus on February 23, 2018, 02:33:43 pmExactly and how can he say that the code works on any platform without showing how much platform dependent code he has written for the library to work. This is only true if you use a already written library and apart from the Arduino stuff i dont know any library that works on many platforms. Not to say that Arduino definitly looses in the overhead discussion(not because of C++ of course).So it really comes down on the project your working on and what your are familiar with. For example i would never use C++ on a 8bit microcontroller. Also most of the time i dont really have the time for writing a C++ library for a project atleat at not at work.

author: nctnico
author_rank: Super Contributor
timestamp: February 23, 2018, 05:10:02 pm
content: Quote from: gmb42 on February 23, 2018, 01:21:48 pmAgreed. The fact C/C++ accepts code which is obfustigated doesn't mean the code has to be obfustigated. Have to watch the video later. Using C++ for embedded has been on my todo list for over a decade now.

author: mart1n
author_rank: Contributor
timestamp: February 23, 2018, 05:57:21 pm
content: An entire video comparing STM32 HAL libraries to a C++ library without linking to it or mentioning the libraries name?

author: Nusa
author_rank: Super Contributor
timestamp: February 23, 2018, 06:45:33 pm
content: Quote from: mart1n on February 23, 2018, 05:57:21 pmIf you'd watched the video, or at least the last 3 minutes of it, you wouldn't say that.

author: Kalvin
author_rank: Super Contributor
timestamp: February 23, 2018, 07:38:58 pm
content: I can highly recommend the book "Real-Time C++ - Efficient Object-Oriented and Template Microcontroller Programming, 2nd. ed." by Christopher Kormanyos.The following video is also a very good introduction for the template-based C++ embedded programming. The idea is to perform compile-time instantiation, polymorphism and optimization using templates instead of traditional run-time polymorphism, which allows the compiler to produce very optimized code. In the video Wouter van Ooijen compares the traditional C implementation to traditional C++ implementation and highly optimized C++ template based implementation.goo.gl/6ttCZAEdit: Changed the Youtube link with preview to this shorter one which will not hijack the thread.

author: thm_w
author_rank: Super Contributor
timestamp: February 23, 2018, 10:15:26 pm
content: Quote from: Nusa on February 23, 2018, 06:45:33 pmCan you clarify, I must have missed it as well. When do we expect this library to be available online?

author: hans
author_rank: Super Contributor
timestamp: February 25, 2018, 10:39:39 am
content: Quote from: jeremy on February 23, 2018, 04:08:42 amYes, I think this is a nice summary how to use C++ effectively for embedded programming. I personally also use std::function quite as alocalcallback to the application. When paired with a template this can be rather efficient as well:QuoteWhich then used with type Tatomic:QuoteThis statement is then repackaged twice (first SetClear operation, then as GPIO SetPinMode) for application code. Don't notice any overhead in disassembly output with -O2:QuoteI think these videos are also a nice demonstration aboutnegativecost C++ programming:https://youtu.be/fRzF7NSF1IIhttps://youtu.be/u615he5wdeoAlso episodes 54 thru 56 show "zero cost" C++ embedded programmingI think the added safety of C++ type system, as well as added abstractions can speed up development massively. For me also C++ code is much easier to unit test than C. It's easier to instantiate a class locally than it is to work with a C module that has uses some local storage, which you cannot reach to reset/instantiate for testing.The piece of code I just demonstrated was from a small toy program playing around with these C++ definitions. I had created a Stm32Gpio object that can be used as in/out, write pins, etc. From that I created a bitbanged SPI driver using an abstract GPIO objects, not tied to the STM32 implementation.Using that SPI driver, it's trivial to define a GPIO expander driver using a 74HC595 or a fancy SPI chip, which can then be used as GPIO over SPI. So basically we've gone full circle back to abstract GPIO objects again, but this time communicating over SPI, transparently. One danger ofcourse is that this detail is abstracted away, then any synchronous GPIO operation becomes very slow. Since most code is written synchronously to deal with GPIO, the application scope is rather small. You could ofcourse implement caching behaviour (e.g. accumulate R/W operations and then commit them all at once), but such caching and requiring flushing is not application agnostic, and thus falls flat down on it's face. I think there are other more higher-level applications that can make better use of abstractions though, e.g. memory devices or sensors drivers.Nevertheless, it was still a funny exercise. Because the SPI GPIO's are "basic" GPIO's again, one could create a bitbanged SPI driver using GPIO that is already going over bitbanged SPI. I cascaded this with 5 chips. Since each GPIO write took 16 bits to transfer, it takes 16^5=1048576 clocks to write a single GPIO at the end of the cascaded chain (a few more actually because of latches or chip selects). With an average SPI clock of 10MHz on a STM32F4, that comes down to a blink rate of about 5Hz when it's running in a while(1) {} loop continuously.

author: Elandril
author_rank: Contributor
timestamp: February 25, 2018, 06:11:47 pm
content: Quote from: Fungus on February 23, 2018, 04:44:53 pmActually that is not really the reason. The C++ standard (as most programming languages by the way) defines the operational part of a loop as astatement. Such astatementcan take several forms:labeled-statement,expression-statement,compound-statement,selection-statement,iteration-statement,jump-statement,declaration-statementortry-block. The form without the braces is anexpression-statement, while the form with braces is acompound-statement. Both are perfectly valid. To be precise there is a small difference between the two: the braces do actually open up another scope.

author: Auslander
author_rank: Newbie
timestamp: February 26, 2018, 08:39:44 am
content: Great video David,Can you post source code you used in video. I'd really like to make comparison C vs C++ against speed, memory footprint, latency etc.

author: NexusKoolaid
author_rank: Contributor
timestamp: February 26, 2018, 04:15:14 pm
content: Quote from: Elandril on February 25, 2018, 06:11:47 pmIsn't that just a yacc-ish grammatical breakdown of what he was talking about - the unacceptability of breaking from C grammar by the contextual disallowing of expression statements?

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: February 27, 2018, 09:00:48 am
content: Quote from: Nusa on February 23, 2018, 12:09:38 pmAnd one can also write:Code:while (what) something, something_else, and_even_moar();Which is ~ as good as:Code:while (what) {something;something_else;and_even_moar();}

author: szechyjs
author_rank: Unknown
timestamp: March 06, 2018, 02:52:30 pm
content: Any chance you'll release your library David?Thanks!

author: rhb
author_rank: Super Contributor
timestamp: March 06, 2018, 04:49:42 pm
content: The problem with conditionals without braces is you can't set a break point on the condition being met. You stop every time it is tested. For conditionals inside loops that run for a long time that makes debugging *very* tedious. I've worked on over 2.5 million lines of old code. One of the first things I typically do is add braces to all conditionals. If I want to stop on the Nth iteration of a loop for N large, I'll put in:if( i == N ){printf( "fubar" );}and set a breakpoint on the printf. Yes, debuggers will let you set a breakpoint when a variable reaches some value. But the value test gets made on every instruction which makes things run very slowly. If you're doing a large 3D FFT and want to check the address of the last value written in each plane of the transform the code will run for a week before it halts. I guess it does give an excuse for not doing anything useful. "I'm waiting for the debugger to hit the breakpoint I set."On processors which employ branch prediction there's no performance penalty at all. That's probably not true for MCUs, but big machines get embedded when it's needed.Personally, I do not and will not use C++ for *anything*. I've spent 3-4 months on two occasions studying the language. I finally concluded no one understands C++, they just pretend that they do. I read obscure programming language manuals for fun, along with books on compiler optimization techniques. So when I say "understand", I'm talking about register level behavior.Object oriented programming has been a tremendous benefit to DRAM makers. All those tables of pointers to functions that will never be applied to an object eat space like mad. A text date and time display now consumes 80 MB of core. Which is why it takes 4 GB of DRAM to run Firefox.My real objection though is this:int main( int argc ,char* argv[] ){new A a;new B b';new C c;c = a + b;}If multiple inheritance has been used it will be necessary to read all the class libraries, the relevant C++ standards document and the compiler implementation notes to determine what the single executable line does. Furthermore, there is no guarantee that the next version of the compiler will produce the same result or even compile the code. And changing the order of parent class declarations will change the behavior.The only "benefit" I see to C++ is that it lets people who don't know what they are doing write things they don't understand. I don't really have any issue with C++ for the sort of things that Stroustrop developed it for. My issue is with proclaiming that everything is a nail and should be hit with a hammer.

author: Fungus
author_rank: Super Contributor
timestamp: March 06, 2018, 05:49:04 pm
content: Quote from: rhb on March 06, 2018, 04:49:42 pmSo muchMust not reply. EEVBLOG isn't the place. This flamewar was done and dusted decades ago.<bites tongue>

author: darrylp
author_rank: Regular Contributor
timestamp: March 06, 2018, 06:27:55 pm
content: Why are people fixated on screen grabbing desktops running resolutions like 1920*1080 to show code ?It's stopping people using mobiles and tablets being to usefully watching these videos.Videos with source code showing line lengths longer than say ~132 characters total shows how bad you are at understanding your viewing audience needs as well as you poor use of desktop estate and if you need lines of code more than 132 characters then your not coding very well !Sent from my HTC One using Tapatalk 2

author: rhb
author_rank: Super Contributor
timestamp: March 06, 2018, 07:42:25 pm
content: Sorry. I really was trying to be good and just comment on the curly brace issue. Just because you can do something doesn't mean you should.I got one of the Plan 9 diskettes at Usenix in 1995. It put an OS, editor, windowing system, Unicode support and an assortment of command line utilities (e.g. ls) in 1.44 MB with room to spare. IIRC it was written in Limbo, but I might be conflating things with Inferno, the other OS Bell Labs was playing with at the time.I recently had to retire my Internet access system, a dual core Atom with 2 GB of DRAM because it no longer had room to run Firefox. I spent 4 years in grad school working on a VAX 11/780 which didn't have 2 GB of disk. And we had lots of disk for the day because we were processing seismic data.All those pointers to pointers to pointers... consume a lot of memory and CPU time.

author: thm_w
author_rank: Super Contributor
timestamp: March 06, 2018, 11:44:11 pm
content: Quote from: darrylp on March 06, 2018, 06:27:55 pmMost editors have the ability to scale the text easily, so he just needs to remember to do that in the future (think it was discussed in the YT comments).

author: NexusKoolaid
author_rank: Contributor
timestamp: March 07, 2018, 12:01:40 am
content: Quote from: rhb on March 06, 2018, 07:42:25 pmMemory and time for vtables - negligible in most circumstances. RTTI and dynamic_cast on the other hand...

author: Fungus
author_rank: Super Contributor
timestamp: March 07, 2018, 09:23:18 am
content: Quote from: rhb on March 06, 2018, 07:42:25 pmThere's only one vtable in memory for eachtypeof object. You can have a billion objects in RAM and they all point to the same vtable. Result: Maximum possible overhead per object isonepointer (and that's only if your object has virtual functions, otherwise it's zero).The reason "why it takes 4 GB of DRAM to run Firefox"isn'tC++. C++ is one of the leanest, meanest programming languages ever*. The reason it takes 4GB is because the old C++ function called "drawAButton()" has now been replaced by a Python interpreter which reads a script file then translates it to a meta language to be interpreted by some rendering API which is a wrapper for a framework that uses a Javascript core running in a sandbox to draw the same square with a border around it as before.This design makes everything more customizable so people can use "themes" (just edit the script!)In practice: Nobody will ever create themes because every single Firefox update will change something that breaks them. All theme creators eventually get pissed off and stop trying to keep up.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: March 07, 2018, 12:15:19 pm
content: Quote from: rhb on March 06, 2018, 04:49:42 pmWithout the braces:Code:if (i == N)printf("fubar");You can't set the breakpoint?

author: Fungus
author_rank: Super Contributor
timestamp: March 07, 2018, 01:32:45 pm
content: Quote from: GeorgeOfTheJungle on March 07, 2018, 12:15:19 pmThat made no sense to me either but it's irrelevant.It's nothing to do with "C++" or "programming style", at most it's just some IDE problem.

author: rhb
author_rank: Super Contributor
timestamp: March 07, 2018, 02:33:47 pm
content: Don't take my word for it, try it. Without the braces it's a single statement that begins with the "if" and ends with the ";". The compiler and debugger don't care about the formatting. Same problem with "d = a ? b : c; "The behavior is a necessary consequence of parsing the source code. Unless you change the grammar it *has* to be that way. The code generated by the compiler will be the same in all 3 cases for equivalent conditionals.Language features that save typing generally incur huge debugging costs. Implicit typing in FORTRAN is the most pernicious of the "save a few keystrokes" features. I won't even attempt to compile an old FORTRAN code until I've inserted "IMPLICIT NONE". I had an automated script that generated the declarations from the compiler error messages. So I could add declarations to a 100,000+ line program in an hour or so. I also put all named COMMONs in an include file and run the mess through the C preprocessor. Just those two steps have caught and fixed more bugs than I can count.If you thoroughly understand the C standard, there is nothing that C++ offers that you cannot do in C. C++ just automates a bunch of stuff to save keystrokes. But TANSTAFL. The price is paid in core and cycles.

author: AlfBaz
author_rank: Super Contributor
timestamp: March 07, 2018, 02:38:50 pm
content: Quote from: crispus on February 23, 2018, 02:33:43 pmYepGPIO_SetBits(BLINK_GPIOz(BLINK_PORT_NUMBER), BLINK_PIN_MASK(BLINK_PIN_NUMBER));vsGPIOx->BSRRL |= GPIO_Pin_x;

author: alexanderbrevig
author_rank: Frequent Contributor
timestamp: March 07, 2018, 03:41:17 pm
content: Quote from: rhb on March 07, 2018, 02:33:47 pmIf you thoroughly understand the C++17 standard then you know that the above statement is false. Even at compile time.The C++ compiler knows much more about the code and can do a lot more optimizations than a C compiler can. In C you can of course write optimized code, but you can do the same with C++.A real challenge would be to find some C program that can't be written at least as efficiently with C++

author: NexusKoolaid
author_rank: Contributor
timestamp: March 07, 2018, 03:50:26 pm
content: Quote from: rhb on March 07, 2018, 02:33:47 pmCode:int N = 5;for (int i = 0; i < 10; i++)if (i == N)printf("Muffins");A breakpoint on the printf statement will be hit exactly once, when I = 5. If you get different results I suggest you update your tool set. That said, some compilers will have a problem when the if statement appears on a single line, but this has nothing to do with the presence or absence of curly braces.QuoteYou seem to be mixing apples and oranges here. Of course the code generated by the compiler will be the same, but the issue that was raised involved the placement of breakpoints. If you review c/c++ grammar you will see that the compiler can identify statements whether they are expressed alone or within a compound statement.

author: GeorgeOfTheJungle
author_rank: Super Contributor
timestamp: March 07, 2018, 04:08:40 pm
content: And in javascript (also a C-like syntax language) you can also set a breakpoint like that:

author: Fungus
author_rank: Super Contributor
timestamp: March 07, 2018, 04:45:50 pm
content: Quote from: rhb on March 07, 2018, 02:33:47 pmIf you understand assembly language there is nothing that C offers that you cannot do in assembler.Quote from: rhb on March 07, 2018, 02:33:47 pmC compilers just automate a bunch of stuff to save keystrokes.

author: rhb
author_rank: Super Contributor
timestamp: March 08, 2018, 12:17:35 am
content: Quote from: NexusKoolaid on March 07, 2018, 03:50:26 pmWhat compiler and debugger on what OS? I've used every major Unix vendor compiler plus quite a few more. It would certainly be nice if you can hit that breakpoint, but I've never seen anything that does it..

author: AlfBaz
author_rank: Super Contributor
timestamp: March 08, 2018, 12:32:45 am
content: Quote from: rhb on March 08, 2018, 12:17:35 amarm-none-eabi-gcc/gdb here on eclipse, no problems

author: AlfBaz
author_rank: Super Contributor
timestamp: March 08, 2018, 12:35:51 am
content: Could it be you are trying to debug code with optimisation or at least no -g option? Break points are harder to hit in this situation

author: Brumby
author_rank: Unknown
timestamp: March 08, 2018, 01:02:08 am
content: Quote from: Fungus on March 07, 2018, 04:45:50 pmDang. You beat me to it.

author: rhb
author_rank: Super Contributor
timestamp: March 08, 2018, 01:06:55 am
content: I'm about to turn 65 and have debugged over 2.5 million lines of other people's code. Most of it very complex scientific and DSP stuff.I'm about to bring up a BeagleBoard X15 so I shall be very interested ti test the assertion. It certainly would be convenient.The price for automating assembly with C is a lot lower the the cost of restricting scope with C++. I happen to remember doing real work on machines with 4 MB of memory.

author: hans
author_rank: Super Contributor
timestamp: March 08, 2018, 08:39:31 am
content: I think rhb has a fair point.Sure C++ offers a bunch of tools to manage complexity, but there are a lot of undesirable constructs that you shouldn't touch on embedded (like exceptions, new operator, etc.), and some abstractions that can generate a huge bunch of code with a single value assignment. Additionally you may find that C++ can fold a whole bunch of expressions in 1 part of your project because all the const and static assignments were setup nicely. But in another setting it may not.For latter C is way more predictable in how it compiles to code. Function callbacks are simpler in C IMHO.Additionally, if you turn the C++ optimizeroffyou may find that code can literally run a dozen times slower. Ofcourse; depends on the complexity of the code and layers of abstraction built. But I think it's atypical that C++ projects will tend to write more abstractions.Binary imagesexplodein size, because all simple 'layered' functions are compiled to separately. Then if you do turn on the optimizer to g (inlining a lot of these statements), you may find you still cannot set breakpoints if you're calling that method from 5 different places and your device only has 4 breakpoints.Now personally I think a lot of these issues can easily be alleviated with unit testing on a workstation, which is a mindful thing to do anyway, and I think the added abstractions and nice "packaging" of agnostic device drivers is worth investing some extra time and optimizing.

author: Fungus
author_rank: Super Contributor
timestamp: March 08, 2018, 12:18:21 pm
content: Quote from: rhb on March 08, 2018, 01:06:55 amIt's strange to think that most "C compilers" these days are really just C++ compilers with a few options turned off.You'd think they'd re-use the same code generator and optimizer for both languages instead of having two - one for C++ and a much better one for C.Oh, wait...Quote from: rhb on March 08, 2018, 01:06:55 amOh, you youngsters. You don't know you're born!PS: Arduinos have 32kb program memory and 2kb of RAM. They're mostly programmed in C++ using a C++ compiler. Go figure.

author: Fungus
author_rank: Super Contributor
timestamp: March 08, 2018, 12:33:34 pm
content: Quote from: hans on March 08, 2018, 08:39:31 amOne of the mantras of C++ design was "you don't pay for what you don't use".If you're not using polymorphism or exceptions then C++ will use no more memory and generate no more code than C.And ... even without those things you still gainan awful lot: eg. Objects make code a lot cleaner and easier to re-use.Explanation: Any language which just dumps everything into a single global namespace is just asking for trouble when you try to copy code from it into another project. C++ puts related variables and functions into little mini-namespaces (aka"classes") which are much less likely to cause problems.

author: rhb
author_rank: Super Contributor
timestamp: March 08, 2018, 01:50:36 pm
content: Quote from: Fungus on March 08, 2018, 12:33:34 pmIf you're not using classes, it's a dialect of C, not C++. Once you start using classes, every object drags with it a table of pointers to all the methods, public and private. If you inherit from a base class, you have a table of pointers to a table of pointers in the base class. I watched a bunch of UI programmers merrily design objects with 4 & 5 antecedent classes even though there was no need for it. "Design Patterns" had just come out and they were hot to be using the latest jargon. Aside from the increased memory footprint, that's a lot of constructors which have to be run to instantiate an object.I warned them at the start of the project (I was strictly doing scientific codes) to keep an eye on their linker dependencies by way of a page from "Large-Scale C++ Program Design" by John Lakos posted on my door. This was ignored until the compile times became intolerable and they had to stop work while they refactored the mess they had made. I was quite startled when one of them pulled a copy of that page out of his desk. He *had* paid attention.I've seen a good bit of "C++" which was actually just C with C++ semantics. In that case the compiler may or may not generate the same code. It depends upon whether the code touches an edge case where the two languages differ.This is the reason for the staggering code bloat. The Vivado FPGA suite from Xilinx is a 20 GB download! Firefox has a runtime memory footprint of over a GB.A well designed and documented library in any language is easy to reuse. C++ requires that you include all the antecedent libraries even if the particular object you are using doesn't reference them. An old FORTRAN code has the minimum possible dependencies as is also the case for assembly and C.In case it's not obvious, I am what Fred Brooks described as a language lawyer. Not only will I tell you that section 8.3.5 says that upon return from a function or subroutine named common may be undefined, I'll also explain that that behavior was included to allow FORTRAN 77 to run on the Burroughs 5000 which was the first stack based machine. It also was a tagged architecture machine. Every word in memory had a a set of bits that recorded the type of the value stored at that location. I'm not aware of any other hardware that implemented that feature though I've read a great many expositions of the virtues of a tagged architecture.

author: Fungus
author_rank: Super Contributor
timestamp: March 08, 2018, 03:19:12 pm
content: Quote from: rhb on March 08, 2018, 01:50:36 pmNo True Scotsman...?Quote from: rhb on March 08, 2018, 01:50:36 pmUntrained programmers?They could do that in any language. If they weren't doing it in C++ they'd be doing it in C# or whatever the language-du-jour is.Writing something like UI codewithoutpolymorphic inheritance is going to be very unproductive. Just teach them to do C++ properly.Quote from: rhb on March 08, 2018, 01:50:36 pmAs noted in a previous post: That's not because of C++.

author: IanMacdonald
author_rank: Frequent Contributor
timestamp: March 18, 2018, 01:54:18 pm
content: Speaking generally (not just for C) the main advantage of OOP is in larger projects where coders are assigned to develop and manage subsections of the code. It allows them to create private functions without having to consider the possibility of namespace clashes with other coders' work.I just don't see why you would want to use OO code for a single-coder project though. You're just making things far harder for yourself, for no good reason. If you can't keep track of your naming conventions, then you need to rethink your working practices because you are writing poor quality code. Using OOP will not change that basic situation. Although, it may act as a gaffertape fix.

author: Fungus
author_rank: Super Contributor
timestamp: March 19, 2018, 07:57:23 am
content: Quote from: IanMacdonald on March 18, 2018, 01:54:18 pmI don't know if it's themainadvantage but I know that the way classes take function names out of the global namespace is something the C diehards usually overlook, and it's abigwin when you're writing large software, yes.Quote from: IanMacdonald on March 18, 2018, 01:54:18 pma) Why is it any harder?b) Associating code with data is often good even on tiny projects. eg. How would you write a traffic light controller that had to control four traffic lights without using objects?

author: nctnico
author_rank: Super Contributor
timestamp: March 19, 2018, 09:13:44 am
content: Quote from: IanMacdonald on March 18, 2018, 01:54:18 pmIMHO C++ is more than being able to use OO and you can code OO style in regular C as well. The big advantage of C++ is that you can avoid using pointers to a large extend and thus make code more reliable.

author: rhb
author_rank: Super Contributor
timestamp: March 19, 2018, 01:17:44 pm
content: Careful use of the C scoping rules neatly solves any namespace issues. People *should* do that as a matter of course, but they don't. Which is sad as all it requires is putting "static" in front of the global variables in a file and *never* using global variables unless *every* function needs them. I've placed file scope variables just before the functions that needed them in some instances so that only those functions saw them.I once wrote a parser in C which had a large conditional with many branches. After I wrote it I realized that every function called from that structure had the same four arguments except for two which had a 5th. To make this obvious I made the 4 arguments global with file scope so that the two functions with an extra argument were obvious to whomever had to read the code later.Pointers are not a problem if you are careful. I've certainly fixed a *lot* of null pointer problems. but I can't recall any I made. But my standard style includes a lot of:if( !ptr ){// report null pointer and exit}else{// get the job done}I once had an assignment to write a string substitution routine. Given a string "old" substitute string "new". This was given to me because I had all my scientific routines done and they were trying to keep me busy. I wrote it twice, once in C and once in C++. The C++ version was 3 times as long as the C version to do the same thing. I don't recall which the project used. I'd guess the C++ version, but that's just a guess.At about this time ('97-98) Les Hatton published a paper in the ACM journal discussing the statistics of several years maintenance on the static code analyzers his company sold. The C analyzer was written in C and the C++ analyzer was written in C++. The programming staff were analyzing C and C++ code for errors, so they were quite expert in both languages out of necessity. The mean time to fix a bug on the C++ analyzer was significantly longer than the C analyzer. Les later wrote a book, "Safer C".

author: Fungus
author_rank: Super Contributor
timestamp: March 20, 2018, 03:42:23 am
content: Quote from: nctnico on March 19, 2018, 09:13:44 amYep.Quote from: nctnico on March 19, 2018, 09:13:44 amTrue, but it's more typing and more bug-prone.Quote from: nctnico on March 19, 2018, 09:13:44 amThat, and a few dozen other things.You're right on the money though, C++ is all aboutincreased reliability and less bugs. Every time you can make the compiler do a bit more work for you then your code improves.A good example of this is the "+=" operator.eg. Which is best:Code:myVariableX += 1;orCode:myVariableX = myVariableX + 1;Obviously the first one. I doubt anybody will disagree that it's easier to get right, makes it easier to see errors, makes code more reliable.Every time I hear a C programmer say"C can do everything the C++ can!"I want to ask them if they'd take the "+=" out of C.It's not needed, right?

author: Brumby
author_rank: Unknown
timestamp: March 20, 2018, 04:09:21 am
content: Quote from: Fungus on March 20, 2018, 03:42:23 amThat's a difference in syntax - and whatever benefits do or do not accrue - there is nothing functionally better in the executable.Anyway, I'm not into the "this" is better than "that" head butting. A lot of the time it is what people know that they champion. There's no way to have a winner there.

author: Fungus
author_rank: Super Contributor
timestamp: March 20, 2018, 04:11:31 am
content: Quote from: rhb on March 19, 2018, 01:17:44 pmOnly if you're working in isolation and always get to pick names which don't exist yet.Even then you'll have problems writing large programs, eventually all your function names will become longer and longer to avoid clashes with existing functions.C++ hasmanyother advantages when it comes to naming functions, eg. you can have several functions with the same name!In Arduino you can type:Code:Serial.print(123);Serial.print(123, HEX);Serial.print(1.23);Serial.print("Hello, world!");In C it would be something like:Code:printSerialInt(Serial, 123);printSerialIntHex(Serial, 123);printSerialFloat(Serial, 1.23);printSerialString(Serial, "Hello, world!");Yes, the second onedoeswork correctly, but...Quote from: rhb on March 19, 2018, 01:17:44 pmYou can do that in C++ as well. Are you rejecting C++ because of things like this?Quote from: rhb on March 19, 2018, 01:17:44 pmCode, or it didn't happen.(and probably had a memory leak)Quote from: rhb on March 19, 2018, 01:17:44 pmWhat if he'd written the C analyzer in C++ and the C++ analyzer in C?

author: Fungus
author_rank: Super Contributor
timestamp: March 20, 2018, 04:18:48 am
content: Quote from: Brumby on March 20, 2018, 04:09:21 amThe point is that there's something better in the source code.Quote from: Brumby on March 20, 2018, 04:09:21 amYep. The only reason somebody would champion C over C++ is that they don't really know C++.(or that there's no decent C++ compiler available on their platform, although that argument doesn't really hold water any more - the C and C++ compilers are usually the same these days)

author: Kjelt
author_rank: Super Contributor
timestamp: March 20, 2018, 08:29:53 am
content: Fact is C is still king in embedded software.My new job they are only interested in my C skills since 80% of the machine was written in C and the youngplayers have problems. I don't care if I have to code C or C++, or Python or whatever.Discussing whats better is useless.On your job you encounter the one or the other or both and you have to deal with it, thats your job.In 10 years we only do mdd and dont even know what compiler is used or code is coming out

author: apis
author_rank: Super Contributor
timestamp: March 23, 2018, 12:37:36 pm
content: C++ is more modern and has more features, no doubt about that. But C has several advantages that may not be obvious: It's more portable. It's simpler and therefore more predictable. That in turn means it's easier to prove it's standard compliant. It's easier to predict exactly what the assembly code will look like, and so on. Something you write in C today is likely to still compile fine in 10-20 years, but the same is less likely to be true for C++.

author: Fungus
author_rank: Super Contributor
timestamp: March 23, 2018, 02:05:31 pm
content: Quote from: apis on March 23, 2018, 12:37:36 pmI'm open to counter-examples but I'm not sure any of those are true unless you're only talking about legacy systems.'Portability' these days usually means writing a code generator back-end for gcc. The same generator will be used by CandC++.Quote from: apis on March 23, 2018, 12:37:36 pmThat one's completely false.

author: apis
author_rank: Super Contributor
timestamp: March 23, 2018, 03:16:47 pm
content: Quote from: Fungus on March 23, 2018, 02:05:31 pmOften if you write complex software in C++ and using one compiler it will not even compile on another C++ compiler without modifications, and that have also been true with older compiler versions versus newer. Thus you can't expect code from 10-20 years ago to compile without problem on a modern version. I know projects that have been abandoned simply because the code was too old and it would be too much work to port it to a modern C++ compiler and libraries.Would also like to see a C++ compiler that is provably standards compliant, something that is much easier to do with a C compiler (because the language is simpler), and that can be critical for sensitive applications.With C you pretty much know what you get down to the machine code level and you can be pretty certain it will compile the same way in the future so it's easier to maintain.I don't agree C++ is a horrible language like some people(https://web.archive.org/web/20140706160843/http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918)but sometimes C is the better choice. Especially if you want the most efficient and maintainable (predictable and portable) code.

author: Fungus
author_rank: Super Contributor
timestamp: March 23, 2018, 03:44:22 pm
content: Quote from: apis on March 23, 2018, 03:16:47 pmIt probably would if they'd followed the standard back when they wrote it.The problem is that a lot of people made assumptions, eg. that iterators of std::vector were raw pointers and thus it was OK to assign values to them (eg. null). It may have worked on a particular compiler back in the day but it was never correct C++ code.(I use that example because I've seen it and dealt with it in real life)Yes, I know the C++ standard is larger than the C standard, but IMHO the most useful subset of C++ is about the same size.Bjarne S. always said that "Inside C++ there's a smaller, cleaner language trying to get out".Quote from: apis on March 23, 2018, 03:16:47 pmSure, but the claim was "Something you write today..."Quote from: apis on March 23, 2018, 03:16:47 pmMy feelings are that C++ has settled down to the point where it's moot for new development.(at least a decade ago, and certainly with C++ 0x11)

author: apis
author_rank: Super Contributor
timestamp: March 23, 2018, 05:46:23 pm
content: Quote from: Fungus on March 23, 2018, 03:44:22 pmAlright, I'll get back to you in 10-20 years time then.I do like C++ but especially for embedded project that are often speed sensitive, operates at very low level, might have a lifetime of several decades, running on uncommon hardware, and often is more safety-critical than your average smartphone app; it often makes more sense to use C. I will not try to stop anyone from using whatever they want to use, I'm sure C++ is the better option in many applications. And now that I think about it, isn't there python for embedded applications as well these days?

author: Fungus
author_rank: Super Contributor
timestamp: March 23, 2018, 06:18:17 pm
content: Quote from: apis on March 23, 2018, 05:46:23 pmAs noted earlier: Nobody would say that "operator+=" isessentialbut it makes things a little bitsaferas well as easier.The extra features of C++ don't just make coding easier, they make it a bit safer, too. Small details but it all adds up. Yes you can do it in C but the code is usually more verbose and requires more scrutiny.If I was going to generalize this I'd say something like this: C++ allows you to move more of the code's complexity up into the library level. This makes the real program logic and layout much easier to work with (more transparent).In C the logic part of the code is usually full of housekeeping/boilerplate code, eg. zeroing out structs before you can use them. Zeroing the struct is something the compiler should be doing, not the programmer. The zeroing just adds a little bit more clutter to the code and its one more thing that can be forgotten when you're having a bad hair day.Quote from: apis on March 23, 2018, 05:46:23 pm(raises eyebrow)Code written using a C++ compiler is necessarily slower or less low level than C?Quote from: apis on March 23, 2018, 05:46:23 pmI don't have massive experience there but I doubt it'll make much difference if you're starting new code today. Is there a modern platform without a decent C++ compiler?

author: apis
author_rank: Super Contributor
timestamp: March 23, 2018, 07:53:47 pm
content: Quote from: Fungus on March 23, 2018, 06:18:17 pmI see your point, and agree that for large complex project the oo features of C++ makes the code more readable and manageable and thus more secure in some ways. Here we are talking about embedded software though, which is typically much smaller and the benefits of oop is smaller. The reason C has an edge here imho is that you have finer control over what machine code is generated. Yes, in C++ the compiler does more for you, but that also means there are more things that can go wrong. For example, if you are forced to switch compiler to another version or maybe even platform and model of the compiler, then you can no longer be certain it will generate exactly the same machine code (or at least it would be a lot harder). And for embedded systems that relies on real time timing and such, that might be enough to break it, and it will be a real headache to debug.Quote from: Fungus on March 23, 2018, 06:18:17 pmC is a lower level language than C++ since you let the compiler do more of the work for you, and C++ will generate automatic crap that isn't always necessary (for most non embedded applications the difference is negligible though). And if you rely on lots of library feature it just gets worse, aaand it's not just speed that is important, codesize is also important for example.Quote from: Fungus on March 23, 2018, 06:18:17 pmYes, there isn't a C++ compiler for all the pic micros for example.

author: Karel
author_rank: Super Contributor
timestamp: March 23, 2018, 08:32:01 pm
content: Popularity of programming languages (in general, not just embedded):1 Java 14.941%2 C 12.760%3 C++ 6.452%4 Python 5.869%5 C# 5.067%https://www.tiobe.com/tiobe-index/

author: Fungus
author_rank: Super Contributor
timestamp: March 23, 2018, 08:54:03 pm
content: Quote from: Karel on March 23, 2018, 08:32:01 pmUsage != enjoyment(or best)

author: Karel
author_rank: Super Contributor
timestamp: March 23, 2018, 09:01:59 pm
content: Quote from: Fungus on March 23, 2018, 08:54:03 pmThe survey is about popularity, not usage.popularity: the state or condition of being liked, admired, or supported by many people.

author: Fungus
author_rank: Super Contributor
timestamp: March 23, 2018, 09:14:44 pm
content: Quote from: Karel on March 23, 2018, 09:01:59 pmNope.The page itself tells youhow those numbers are calculated:QuoteIt could be that Java is #1 because Java causes the most problems (and therefore the most number of pages dedicated to solving them).Or maybe Java is #1 because it's almost obligatory at enterprise level (and therefore the most number of expensive consultants are after that money).

author: KX36
author_rank: Contributor
timestamp: April 03, 2018, 08:21:45 pm
content: If I may stick my newbie head above the parapet for a second and ask a question about the code in the video...This Pin class template.. Class templates aren't classes themselves, they generate classes from the template right? So does that mean a new class is generated for each combination of port and pin, or is that not the case because the port and pin template parameters are non-type parameters so since they are always the same type it only generates the class once, or something else?I've been trying to implement my own Pin class template as I like the idea. I've put a static member variable in it and that is definitely generated once for each combination of template parameters (as seen by the size program) If I make 2 objects with the same port and pin it doesn't generate the variable again, which leads me to think a new class is generated for each combination of port and pin template parameters. (For my template parameters, Port is an enum, pin is a char.)Cheers

author: Fungus
author_rank: Super Contributor
timestamp: April 03, 2018, 09:14:56 pm
content: Quote from: KX36 on April 03, 2018, 08:21:45 pmYes, but if you do it right the compiler will inline everything and optimize the pin changes all the way down to a single machine-code instruction.

author: Karel
author_rank: Super Contributor
timestamp: April 04, 2018, 06:29:59 am
content: Quote from: Fungus on March 23, 2018, 09:14:44 pmA bit like why windows is most used on the desktop, not because it works better?

author: AlfBaz
author_rank: Super Contributor
timestamp: April 05, 2018, 01:10:50 am
content: Quote from: Fungus on April 03, 2018, 09:14:56 pmSettle down mate. I'm looking through the arm instruction set and nowhere do I see an instruction that takes a collection of bit patterns and stores them into several different, selectable locations.The beast we are taming is a complex, feature laden micro that requires a lot of peeking and poking to get the job done. Putting together a reusable HLL construct in any language is going to take a significant amount of work not matter what language you use

author: Fungus
author_rank: Super Contributor
timestamp: April 05, 2018, 08:44:42 am
content: Quote from: AlfBaz on April 05, 2018, 01:10:50 amI mean each individual pin change, not a whole list of pin changes, obviously.The point I was making was that it doesn't matter if "a new class is generated for each combination of port and pin", the compiler can optimize all that away (and does so - I've checked several times).The reason I'm being so deliberate about replying to this point is because a lot of this topic has been C programmers imagining C++ bloat. Statements like "a new class is generated for each combination of port and pin" are bound to unsettle them.

author: AlfBaz
author_rank: Super Contributor
timestamp: April 05, 2018, 03:05:53 pm
content: Quote from: Fungus on April 05, 2018, 08:44:42 amI keep seeing the phrase "If you do it right" when it comes to c++ on embedded platforms. How deep into c++ compiler theory do you need to go to avoid doing it wrong?Don't get me wrong, I like c++ features and have used it PC's but I've never bothered with compiler output there

author: Fungus
author_rank: Super Contributor
timestamp: April 05, 2018, 05:45:15 pm
content: Quote from: AlfBaz on April 05, 2018, 03:05:53 pmGood question.A better question might be, "What do you have to do to make it gowrong?". I don't know the answer offhand but I suspect it won't be easy.Idoknow that compilers are amazingly good at reducing constant expressions down to the result value.eg. This:float x = (sqrt(2.0)<1.0)? sqrt(sin(1.0)): tan(acos(0.5));byte y = *(byte*)&x;Will reduce down to this:byte y = 0xd8;(I just tried it on the Arduino compiler, it really does that...!)Moral: Don't worry too much about the compiler optimizing away a few bitwise operators in templates.

author: andyturk
author_rank: Frequent Contributor
timestamp: April 05, 2018, 06:59:52 pm
content: Quote from: Fungus on April 05, 2018, 05:45:15 pmI think you should worry, or at least be aware of what the compiler's going to do.In particular, if you're going to instantiate a template multiple times, it's basically the same as copy-n-paste. You don't have to maintain all the generated source, but the compiler and linker need to deal with the resulting object code just as if you typed it all in yourself.So, for instance, you wouldn't want to put "big" methods (i.e., with lots of compiled code) in the template. Factor those out into a base class and have your template only deal with what's necessary to distinguish the instances. Don't put static variables in the template unless you really need one per instantiated class.I use C++ for my GPIO pins too, but not with templates. Generally speaking, I don't care about ultimate speed or minimum code size, I want a higher level interface to what a "pin" is that I can pass around (usually by reference) to other modules that need GPIO to get work done. E.g., a SPI slave might need a chip select pin.

author: JS
author_rank: Frequent Contributor
timestamp: April 27, 2018, 06:38:40 pm
content: Can I ask a question and you help me?I've just started to play around with some STM32 (I bought a few bluepills and a discovery) and after a few days I have the setup running for C, STM32CubeMX to generate the projects including FreeRTOS, SW4STM32 IDE (On OSX) and ST programer to load the bin files to the board.Now the question, how do I go from this to C++? I don't have any against it (just know less C++ than C but I guess that is solved with time) My question is about the programming environment, how to set up C++ IDE, libraries to get it up and running, an RTOS, etc. Getting it to work with C was ok for me, it did took some time to get all running on OSX but it's running.JS

author: andyturk
author_rank: Frequent Contributor
timestamp: May 01, 2018, 11:10:38 am
content: Quote from: JS on April 27, 2018, 06:38:40 pmIt may be as simple as just renaming your .c files to something like .cc or .cpp. That will tell the compiler you're using now to treat your existing source code as C++. You'll probably see a bunch of new warnings and maybe some errors.Ideally, code should compile clean (i.e., zero warnings, zero errors) with all the compiler warnings enabled. It's likely that all the library code you're using with C right now is alreadyset up to compile correctly in a C++ environment.Your code should (eventually) work the same way as C++ as it did as C, but one significant difference is the names that end up in the object files will be"mangled". This usually isn't a problem in practice because the debugger/IDE can demangle names it finds in the object code.Once you've got everything converted over, just start small. Try a namespace. Create a simple class. The first embedded project is often a "blinky" app. How would you do it differently with C++?Here's one attempt:Code:#pragma once#include "panamint/rtx5/thread.h"#include "panamint/rtx5/kernel.h"#include "customer/nrf52/pin.h"namespace customer {namespace project {class BlinkThread : public panamint::rtx5::SizedThread<400> {public:using Pin = customer::nrf52::Pin;using timeout_t = panamint::rtx5::timeout_t;BlinkThread(Pin &led, timeout_t on_time, bool on_state): SizedThread(), led_{led}, on_state_{on_state}, on_time_{on_time}, off_time_{panamint::rtx5::msec_to_ticks(1000) - on_time_} {}virtual void run() override {while (true) {led_ = on_state_;delay(on_time_);led_ = !on_state_;delay(off_time_);}}protected:Pin & led_;const bool on_state_;const timeout_t on_time_;const timeout_t off_time_;};} // namespace project} // namespace customer

author: JS
author_rank: Frequent Contributor
timestamp: May 06, 2018, 01:48:01 am
content: Quote from: andyturk on May 01, 2018, 11:10:38 amThanks! I'll try tonight and come back.So C projects should work as C++?Where do I get the libraries to work with STM32F1? the official libraries are for C, or should I rename the libraries as well?Thanks again!JS

author: andyturk
author_rank: Frequent Contributor
timestamp: May 06, 2018, 02:32:07 am
content: Quote from: JS on May 06, 2018, 01:48:01 amYup, you should be able to compile a C project (with slight modifications) with a C++ compiler. Of course, the closer your C code is to being standard compliant (e.g., C99), the better. If you've got a lot of implicit conversions between integers and pointers for instance, C++ won't like that.When you "convert" your own source code to C++, you'll still keep using the OEM libraries in their original form. C and C++ are compatible that way.

author: JS
author_rank: Frequent Contributor
timestamp: May 06, 2018, 03:38:50 am
content: Ok, 46 errors and 2 warnings. 44 of them "(blah blah) could not be resolved" (first blah is field, symbol or type, second some designator) The other two errors were invalid argument. The two warnings also overlap with two errors. I'm using STM HAL libraries here so I don't know if C++ compiler it's missing them or what, I copied a working C project, renamed the sources and tried to run it.Rebuild the index and errors go away, it does compile, but the compiled file doesn't work as it did when it was a C project.Quote from: andyturk on May 06, 2018, 02:32:07 amWhat kind of modifications should I expect to need? My code is automatically mostly generated by the STM32cubeMX, I added a line or two to get it started doing something (driving a PWM pin)JSPS:I fell like highjacking the thread, should I start a new one asking for help in this and leave a link?

author: andyturk
author_rank: Frequent Contributor
timestamp: May 06, 2018, 04:13:15 am
content: If you push your project up to a git repo somewhere (e.g., github, bitbucket, etc.) I'll take a look.

author: JS
author_rank: Frequent Contributor
timestamp: May 06, 2018, 01:23:18 pm
content: Quote from: andyturk on May 06, 2018, 04:13:15 amHere it is:https://github.com/CyborgJ/PWMJoaquin4.gitThe only line of code I've done there is line 100 of main.c in /srcOther than that is the generated code from STM32CubeMXJS

author: andyturk
author_rank: Frequent Contributor
timestamp: May 07, 2018, 04:22:31 am
content: I cloned and compiled your project with ac6. It seems to build without any warnings or errors, but doesn't have any C++ code as far as I can tell.Simply renaming main.c to main.cc produced 200+ errors. From a pure compilation perspective, I think those can be easily fixed, but perhaps ac6 is confused somehow. I'm not an expert in Eclipse/AC6 (and don't want to become one either).I sent you a pull request (PR) with some changes and an example C++ class that's called from main().

author: JS
author_rank: Frequent Contributor
timestamp: May 07, 2018, 06:43:53 am
content: Quote from: andyturk on May 07, 2018, 04:22:31 amThanks for all the support! That's right, just C, one of the first examples I managed to run on the µC from Cube.For what I can see, with C++ is not getting the same paths for linked resources, and for some reason I can't fix those as I do with C, seems to ignore the project linked paths as I add the necessary ones and just keep the same errors.I'll take a look for the pull request and come backJS

author: RedCali
author_rank: Contributor
timestamp: November 11, 2024, 10:10:14 pm
content: Is the source code some where available for view/ download?

author: Nusa
author_rank: Super Contributor
timestamp: November 13, 2024, 12:47:10 am
content: Read the thread. If the links are broken, it's probably because the thread died over six years ago.