Embedded - 137: Pausing to Think

Episode Date: February 3, 2016

Dan Saks answers many questions about C++ in embedded systems: where it works, where it doesn't, and a path to getting started.  Dan Saks is the founder and president of Saks & Associates. He was a ...columnist for The C/C++ Users Journal, Embedded Systems Design and several other publications. He also served as secretary of the ANSI and ISO C++ standards committee in its early years.  We touched on some of his articles: Poor reasons for rejecting C++ Preventing dynamic allocation Calling constructors with placement new Andrei suggested Sams Teach Yourself C++ in One Hour a Day, Seventh Edition by Siddhartha Rao as a good primer for experienced C programmers reluctantly learning C++. Like robots? Check out the job postings at iRobot. If you like what you see, email Chris Svec. (Yes, the guy who was on 78: Happy Cows.) Contest for Making Embedded Systems will end Feb 5, 2016.

Transcript
Discussion (0)
Starting point is 00:00:00 Welcome to Embedded FM. I'm Alicia White with Christopher White. This week, we are going to talk to Dan Sachs about C++. I'm very excited. But before we get started, the contest to win my book is still going on until Friday, February 5th. So that's coming up real soon. For this one, you are to send your favorite fictional robot to me and or send your resume to Christopher Svek at iRobot, where you can make non-fictional robots like the Roomba and the Bomb Disposal Robot. They are looking for all sorts of help from cloud and Android developers to embedded robotics. The jobs are in Boston and Pasadena. Check the openings in the show notes. So send your resume to chrissvec at iRobot.com and send me your favorite fictional
Starting point is 00:00:52 robot to enter the contest. Okay, now let's get to Dan. Hi, Dan. Thanks for joining us today. Hi. Could you tell us about yourself? Okay, I spent a number of years early in my career as a software developer, a salaried employee, and then later as a hired gun. However, I've spent the bulk of my career helping other programmers program better, first as a classroom teacher at a university, then as an independent training firm. And I also spent a fair amount of time writing columns for a variety of print and web publications, including the C++ Users Journal and Embedded Systems Design. And I also served as the secretary of the International C++ Standards Committee during its early years.
Starting point is 00:01:48 And for the last 20 years or so, my primary interest has been in using C++ to develop embedded systems. Strangely enough, that's exactly what I want to talk to you about today. Wow, that's strange. Before we get to that, we have been doing this lightning round where we ask you questions and hope for one-word answers. So, let's try that. Chris, do you want to go first this week? Sure. The first question is entirely appropriate to this week's discussion. Object-oriented or procedural object-oriented favorite programming language c++ thank you softballs it's really not a shock is it yeah programming language you think should be taught in the first cs course in college
Starting point is 00:02:41 probably python possibly java should we bring back the dinosaurs course in college? Probably Python, possibly Java. Should we bring back the dinosaurs? No. Beach or mountains? Oh, mountains. Mac or PC? PC. Would you rather use function pointers, a go--to statement or have lunch with a large spider
Starting point is 00:03:10 function pointers little or big andian little favorite c or c plus plus keyword either operator or template um okay let's go into like the actual material here um i like c i have been using c for two decades at least um the whole thing i have to ask you is why do i need c++ why do i need to bother well um need is uh maybe that's the operative you don't need it obviously there are people who do productive work in c and and do it reasonably well um and when you say and why bother? Well, if you view it that way, I'm not sure that I can make a compelling case. I find that I was naturally drawn to it. It just made programming in my assessment more pleasant. I found it assessment, more pleasant. I found it to be more expressive. I found that C++ did a better job of catching my mistakes,
Starting point is 00:04:33 defending me against my own frailty. And so I was just drawn to it. And I think that those are the reasons. It's not that you should feel like, oh, gosh, why should I have to do this? It's that you should want to do it. You should say, oh, this is a tool that's going to make my life better. But if you see it as a burden, then don't do it. Well, that was a shorter show.
Starting point is 00:05:02 No. To be fair, and I should, you know, state preferences here, because you should always know the political parties are the people you're listening to. Chris, you're very C++ pro, aren't you? I am fairly C++ pro. If you're going to program in a C-like language. I like C++. I've used it in many projects and many embedded projects up until my most recent one, which is Albin in C. And like Dan says,
Starting point is 00:05:34 there's many things I find compelling about it from a structural point of view and also from, I like the word he used, an expressiveness point of view, which both saves time and kind of keeps you out of trouble sometimes. But I do work with a number of people who are colleagues who are skeptical, especially on small embedded devices.
Starting point is 00:05:57 I find it weird that people are so skeptical. Oh, wait a minute, I was supposed to give my political party, but we're going to get back to that. I was against C++ in 1999, very strongly. The embedded compilers didn't support it. My team didn't know it. Everyone wanted to use only their particular favorite feature. So trying to move over to C++ slowed us down.
Starting point is 00:06:20 But that was 15 years ago. And now the compilers support it and most people coming out of school know it a lot better and they are more and if they come from javascript or python they're just it's easier for them and so you were saying the embedded small chips. Arduino, it's an 8-bit processor. It uses C++. You can no longer tell me that C++ can't go on embedded systems if an 8-bit microcontroller, that's what people use for it. So I'm not buying that excuse anymore. But so I'm more comfortable in C, but I'm interested in C++. I think
Starting point is 00:07:11 there are some things that are much easier there, but I cannot manage to convince anybody to even try it. I feel everybody should make informed decisions about which language they're going to use, just like you'd make an informed decision about which processor you're going to use. And so I wanted to talk to Dan about how do we become informed? That was a handoff, Dan. Sorry, I did lecture there for a bit. It was a bit of a rant. It was a bit of a rant, sorry. No, I was pausing. I was pausing to think. Okay. That's allowed. Yeah. Well, I have a hypothesis about what one of the issues is with respect to the C communities embrace or failure to embrace C++. And that is that many, not all, but a sizable portion of the people who program in C are people who did not major in computer science in school.
Starting point is 00:08:15 They studied other disciplines like electrical engineering or systems engineering or computer engineering, something like that. And programming was sort of, it wasn't their main line of study. It was simply programming languages were tools you used to get the job done. And in that context, and in fact, I experienced this in my own studies at school, I had instructors who, even in computer science courses, were primarily interested in teaching concepts like algorithms and data structures or computability and things like that, but we still did exercises using some programming language. But they would often just say,
Starting point is 00:09:02 and in this course, you're going to program in in lisp and you can buy the book in the bookstore and read it i'm not going to teach you the language and so the actual act of programming was not something that was taught it was people would self-teach programming languages and And so I think a large part of the Z culture is any language worth using is a language you can teach yourself. And C++ doesn't fit that. C++ has a lot of nuances, some features which are not self-evident, and it really helps to learn the language, either through formal instruction or under the guide of some mentor, some experienced C++ programmer.
Starting point is 00:09:52 And it seems to me that a lot of C programmers, they react adversely to that. They don't want to have to go through that period of study and that period of a loss of productivity in making the transition to the new language because they don't see that it's worth it. Now, I think the C++ community may be hurting itself in this regard as well. I was fortunate that I learned C++ just as it was starting to become popular. And in fact, I watched the language and learned the language as it evolved. So the C++ that I learned didn't have templates.
Starting point is 00:10:36 It didn't have exception. It didn't have runtime type information. It didn't have the entire STL. And so I was able to learn those things step by step and adjust my programming style to learn those new features. But now we have a much more mature language with a large feature set and a sizable portion of the C++ community advocates that the right way to learn the language is to learn it like it's not based in C, that you don't use arrays, you use vectors. You don't use pointers and structs, you use the list class or the map class. And for a large number of applications, that is in fact the right thing to do. And if you're teaching university students programming from scratch, it's probably the right way to teach it.
Starting point is 00:11:28 But when you have industrial programmers with a very large code base of existing C and you're trying to get them to migrate that style to this more modern approach, you get a real clash of cultures you get people who are used to the c programmers used to programming a certain way and being told by the c++ programmers well all that stuff you're doing that's that's no good that's so passe and you should be doing it this way and that way and i my reaction is no cut them some slack that There's nothing wrong with learning incrementally. In fact, the reason why C++ is so popular is because it piggybacked on the popularity of C at the beginning. And I think there are people in the C++ community who forget, hey, you learned by spreading it out over many years.
Starting point is 00:12:21 Why isn't that okay for other people to do it and so it's harder to find people who are still advocating the transitional approach to learning c++ by starting with c it's in fact often very much frowned upon by parts of the c++ community and and i think they're as i say they're right in certain application domains you teach it like it's a new language but i don't think that works for the embedded community no we've got a lot of code we can't just walk away it's not just we've got a lot of code it's the resource constraints because you mentioned stl um which is the standard template library right the standard template library which has lots of built-in classes for things like containers and maps
Starting point is 00:13:06 and all sorts of good stuff that you... Huge. That everybody on C-based embedded projects, that's kind of the first, oh, we need a linked list. So somebody's got to go implement a linked list for the 4,000th time and write all the same... I did that last week.
Starting point is 00:13:20 Same bugs all over again. Or you need a hash table or you need a map. And you have to do it your particular way because you're on an embedded device and you want to save resources. I think that's where I get a lot of pushback from colleagues also is, oh, C++ is too bloated because they see the STL, they see things like that, and they say, we can't possibly support that on a small chip. And for a large part of it, they're're right and that's where coming to it from a c point of view and saying okay what can i what things can i take from c++ and use from c++ without necessarily
Starting point is 00:13:53 acquiring the whole thing uh from for this device does that make sense is that as does does that match your experience okay yes i mean that's that is the way my training materials are structured is that i act when i teach embedded programming in c++ we actually start in fact the way i developed my course materials in the first place was i acquired an evaluation board and when you typically acquire an evaluation board from some vendor they give you it used to be they'd give you a disk now you can just download off of the web a a bundle of tools the a c and a c plus plus compiler linker etc plus they give you lots of programming examples that show you how to blink lights and respond to button pushes on the on the board and those examples tend to be written in C. And so I simply
Starting point is 00:14:47 took a bunch of those examples for a particular board and said, how would I rewrite them in C++ and take it through incrementally? As I go through changing structures into classes and changing certain functions into overloaded operators, or changing hash defines into enumerated types and things like that, I'm constantly measuring to see, have I introduced any overhead? And what I found is there's an immense amount you can do at the low level, modeling, for example, memory map devices as classes, which introduces zero overhead. I mean, really measurably zero overhead
Starting point is 00:15:27 and the key is to uh to take it slow and understand how constructs like classes are translated into the equivalent c code and it's really not hard it's a very direct mapping and once you get comfortable with that there's a great deal of power in that. And what you have to do is tune out the people who are telling you, well, that's not real C++ because you're not using this feature or that feature. And I say, what do you mean? It's better than what I was doing before. What? Shouldn't we all just skip the polymorphic templates? Well, I find, by the way, templates are actually incredibly useful.
Starting point is 00:16:12 It's the polymorphous and the dynamic binding that I find to be less useful in low-level applications, but it still pops up once in a while that there's a use for it. Direct mappings seem like syntactic changes for no reason. What sort of, you mentioned pound defs to const, or pound defs to enumerated types. I can sort of see that because then you,
Starting point is 00:16:41 it's like having types, and I like having types because I like it when the compiler tells me, hey, you idiot, you just tried to put a UN32 in a UN8. Maybe that wasn't what you meant to do. At least cast it so I can figure it out. If I wrote compilers, the error messages would be much more amusing.
Starting point is 00:17:00 And so I understand the idea that types are a good thing. And so going from pound defs to enumerated types, that makes sense. It's a safety thing. But we had enums in C. I mean, that's a style difference. What are the C++ things I can do and how will they make my life better other than just straight translation? Well, one of the fundamental mental shifts that takes place when you go from C to C++ is understanding that the treatment of types is stricter, generally stricter in C++ than it is in C.
Starting point is 00:17:41 I'll give you a couple of examples. I was actually kind of shocked to look at the C standard and find that, in fact, converting a pointer of one type to a pointer to another type is actually permitted. For example, it's okay, according to the standard. It's super useful. Converting a pointer to a float into a pointer to a long for example i've done that now what c compilers generally do is they issue a warning for that they don't reject the program they just say you know unless you're at the the lowest level of warnings where you say don't bug me about anything which you should about anything. Which you should never be on.
Starting point is 00:18:26 Pardon? You should never be on that level. Yes, you shouldn't. But it does come out on most compilers as a warning, not an error. Whereas in C++, they say it's an error. I'm not going to compile your program if you do this. And there are other things like, for example, with enumerations, the C treatment is that an enumeration is simply an integer type. You can treat any enumerated type like an int.
Starting point is 00:18:54 So that means that you can have an enumeration for the days of the week, Sunday, Monday, Tuesday, and another enumeration for the months January, February, March, and you can assign a variable of type month the value Wednesday in standard C. And in C++, you can't. They say, no, those are different types. Now, C++ does allow conversion of an enumeration to an int, but it doesn't allow conversion of an int to an enumeration. Whereas C will let you go back and forth. And again, if you have a compiler which has as an enhancement warnings to catch that, then it will do that. And of course, a lot of people say, well, I just use Lint or some other static analyzer. And I say, well, that's a good thing too. But the C++ approach is,
Starting point is 00:19:50 hey, we just build that into the language. And so in general, the enforcement of types is stricter. Yeah, I was about to say that. In C++ than it is in C. Go ahead. I was about to say that, yeah, it seems somehow backwards to expect to, a static analyzer tool to fix problems in your language.
Starting point is 00:20:11 It seems like fundamentally there's a problem with your language if you need to have tools to find errors like that. But no, sometimes you want to be able to switch back and forth because you don't have enough. Never mind, I'm not going to have this argument. We have cortex processors now with plenty of memory. We don't need to be that stingy. There are ways to. There are ways around it if you must. Unions.
Starting point is 00:20:35 Oh, sorry. Well, casts. Yes. Casts. You can always force cast something if you really want. Yeah. Okay. So part of the design intent of C++ is to both tighten the type checking
Starting point is 00:20:52 to make it that the compiler is more of your ally in checking you against your own mistakes. But then C++ turns around and gives you facilities so that well-written C++ can actually use casting much less than C. And an example of that is that the C way of copying blocks of memory is to use something like memcopy. And the parameters for both the source and the destination in memcopy are pointer to void. And pointer to void is essentially an unchecked pointer. So you can call memcopy and you can say, I want to copy this array
Starting point is 00:21:38 of ints to an array of long doubles. And it'll copy them byte by byte and you'll get the joy of debugging that sometime later whereas in c++ you're discouraged from using void instead what you do is you'd write a copy template and the template you could specify it can only be used to copy something of one type to another array of the same type you can only copy array of into array event an array of the same type. You can only copy array of int to array of int, an array of double to an array of double. And when you do it that way, you get code which is now type safe. It's easier to catch at compile time errors where you accidentally transform the types. And so the net effect is you don't have to use casting to um to shoehorn types into a common function and so that makes a lot of sense what else do you have for me that's just one thing i mean c++ is a whole big language i know because this book is huge well i mean there's
Starting point is 00:22:41 the elephant in the room which is the the the object-oriented nature of C++ versus C. Do I have to use that? Alternatively, my C is already object-oriented. In the sense that, well, when I talk about doing object-oriented programming in C, what I'm talking about is using structs and functions that have a parameter of type pointer to that structure type in a
Starting point is 00:23:08 disciplined way, where essentially the function, the parameter pointing to that structure we think of as the this pointer in C++ or the self pointer in some other object oriented language. The C++ way of doing it is functionally equivalent in the sense that
Starting point is 00:23:30 whenever i test this i always get almost exactly the same code in fact though i will say um the last time that i did some real thorough tests on this, I found out that the C++ was sometimes slightly better because the, and my inference is that the C++ compiler knew that the this pointer was special. And so it could take certain measures in terms of parameter passing in registers to actually produce better code. Whereas the c compiler would look at that parameter and just say oh it's just one of many parameters what makes me think that one's special and so on many platforms the code comes out the same but if there's a disparity my experience has been that the object-oriented code in c in c plus plus actually comes out a tad faster. But the big notational advantage
Starting point is 00:24:27 of using object oriented programming in C++ is that it also includes access control. You have the notion of public and private. And so you can, whereas in a C program, all you have is that the struct, all the members are public. And therefore, you can't put the same constraints on the casual user of your object type to say, you can only access this part of the interface. To the C programmer, the entire struct looks like the interface. interface and so that gives the designer of that object in C less freedom to make later changes without worrying oh I might break somebody's code because they poked around in this thing and even though my comments said don't touch it it was only a comment in C++ it's a language tool that enforces the rigorous nature of the interface.
Starting point is 00:25:31 What about the people who say it uses a lot more dynamic memory, which in an embedded system, I'm still having trouble using dynamic memory. It never quite goes the way I want it to. Is C++ required to have dynamic memory? No, no. A lot of people say they don't want to use C++ because it uses more dynamic memory, and I don't quite know where that comes from. I don't either.
Starting point is 00:25:57 I've repeated experience where I say to people, show me the example that you're talking about, and it's typically the response of well i'm sure i had it somewhere or you know somebody of mine told me well that was his experience and i took his word for it but um i keep chasing that one saying show me the example and it's a phantom because i know i i do tons of this this kind of work in terms of crafting low-level drivers and i use classes and i use namespaces and i use operator overloading and i am able to just avoid using dynamic memory. In fact, there are techniques that you can use to actually get compile and link time warnings to tell you that you've inadvertently used dynamic memory. What kind of techniques?
Starting point is 00:27:01 Well, actually, I wrote this up in my column at embedded.com. I wrote a column on exactly that. I also had some lecture material on that from the Embedded Systems Conference. And I can't remember exactly what the title was, but if you give me a moment, I will find it. We can get a link for the show notes after the show. Yeah, you can. Yeah, we'll worry about resolving that later. But yeah, I can provide a link to the article which showed some of those techniques.
Starting point is 00:27:37 Basically, the idea is that you, in C++, the global operator new, when you write a new expression, you say P equals new T, meaning P is a pointer and I want to allocate a new object of type T and the address of that be assigned to P equals new T. The compiler actually translate that into a call on a global function named operator new. And the C++ standard allows you with certain restrictions to write your own
Starting point is 00:28:10 implementation of operator new that's specifically specified in the c++ standard that if you follow these rules for a valid replacement function that follows certain interface conventions certain functional characteristics you can write your own replacement for operator new and the trick is you can write a replacement for operator new which satisfies all of the interface constraints but is implement implemented in a way such that if it is in uh linkedin at link time it causes a link error and so basically you don't use the new keyword just like i don't use the malloc library call exactly if i don't want to use dynamic memory and right but the problem is in c if you call a function that calls malloc you may not know it exactly and so i could force it if
Starting point is 00:29:08 anybody called new it would cause a problem well that leads me to another one of the things that i've been that people have said to me which i find very odd which is well we have all these programmers and if we switch to c++ we'd have no way to prevent them from using language features we don't want them to use. Yes, I like that. Which I find strange because that's true of C as well. There's plenty of very, very bad things you can do in C. There may not even be language features.
Starting point is 00:29:36 It may just be because C is so powerful and low-level. I don't really have a good response for that because it's sort of like, well, yes, that's a problem with programming, not with language. Have you encountered that one? Yeah, actually, I was speaking at a conference last fall on exactly this subject. And one person in the audience said that he's a manager of teams that develop embedded systems in C and they have tried repeatedly to do things like hire new graduates who know C++ and have them be sort of like the local mentors to move the team towards C++ and once again this cultural clash seemed to kick in
Starting point is 00:30:27 which is that these new hires were taught c++ in a in in the modern fashion you know they everything was written in terms of vectors and maps and lists and so on. And when they were confronted with this embedded software that was using arrays and unions and things like that, they couldn't connect it up. The new hires were using features that nobody else could understand. And so they had a choice, which was, okay, we can stop all production and train all of our developers in C++, or we can try to rein in the newbies. And ultimately, as a matter of management control, they just told the newbies, just use C. And that's a human problem. It's not so much a technical problem
Starting point is 00:31:38 as it is a management problem. And I don't have a snappy answer for that. You have to look at your available resources. You have to look at your tolerance for risk and your budget for training and things like that. But there isn't a simple answer to that. And I hear, I hear, I've never actually tried C++, but I hear that it causes, that it kills baby harp seals or some sort of other outlandish. Yes. Yeah. How do, so yes, you need to train your team and ideally you need to train your team together so that they know what each other knows but if i'm alone or we're we're consultants so we don't always get to control the teams or even be
Starting point is 00:32:35 part of them for very long how do we gently push people and say this is an option and it is a good one because well generally my preferred approach is to take a lot of the risk away and so i i'm a firm advocate that the proper way to bring c++ on board in those environments is to nibble away at it a little bit at a time and a class here and a gnome there pardon a class here and an enum there and a const everywhere and yeah whatever that well yeah i think the big payoff generally what i advise people to do is first thing is just take all of your c and recompile it as c++ because it works mostly oh yeah i've never had any problem with that the the only thing that i've ever seen uh crop up is that you might have some user identifier which in c which happens to be a keyword in C++.
Starting point is 00:33:47 So you have to rename something. The other issue is the way the compiler treats type checking. Is that things that compiled without complaint in C may provoke a complaint in C++. And the way you eliminate the complaint is by adding a cast initially. Which you should have done anyway. Yeah, if you were using a tool like a static analyzer, yeah, that static analyzer would have made you do it. Or even just looking at your warnings in your compiler.
Starting point is 00:34:20 That's right. So then from there, the low-hanging fruit is things like the use of reference types, which are, in my opinion, sometimes a nicer way to package function interfaces. Other low-hanging fruit are things like function overloading. What are reference types? A reference is, there are different ways to explain it. The mechanistic way to say it is, it's really a pointer in disguise. It's that when you declare a reference to an int, you use, instead of the star operator or the asterisk, you use an ampersand. Say R is a reference to an int you use instead of the star operator the asterisk you use an ampersand
Starting point is 00:35:07 say r is a reference to an int and when you declare it you bind it to an object you say this reference is referring to some other int n and after that you can use the reference variable r as an alias for whatever it's referring to, N. Now, the underlying implementation, the dirty little secret is they're implemented using pointers. They're pointers in disguise. And I know that some C programmers look at this and say, well, pointers were bad enough when they were out in the open. Now you want me to disguise them so I can't see the indirection. That seems like a disaster waiting to happen. But it actually has a lot of nice properties with respect to crafting more friendly and type-safe interfaces.
Starting point is 00:35:54 And they're easy to use and they incur no performance penalty. And so you said the next one was function overloading. That's when I call a function. I have two functions of the same name maybe with different parameters yes for example in the c library there are functions like put char put c f put c f put char whatever uh and uh put s f put S. And the problem is that they're all variant spellings on a function named put. Now, when programmers talk about this, I've never heard anybody say my program F put C to character. You say it put the character to standard out or it put it to file F. You don't feel the need to say exactly which put function.
Starting point is 00:36:48 In other words, in our own minds, we overload it. And I know, I wish I had back all the time I wasted crafting a system of names for a bunch of related functions in C where I want to have a half a dozen or more functions, which all doing a similar task but on a slightly different combination of parameter types and so you start coming up with a name and you start using it for a while and you realize oh I didn't name that well because now I want to add another function and it doesn't fit the naming pattern. And in C++, they're all functions named put,
Starting point is 00:37:27 all functions named get. And as long as the parameter list is sufficiently distinct for each one, the compiler sorts it out. And I think it's a real aid to usability. Put's a really good example for that. I don't think I've ever heard an example that made that much sense
Starting point is 00:37:45 because yeah, you know, if I pass it a file, then I want it to be F put. And if I pass it a single character, I want it to be put C. And yes, that makes a lot of sense. Thank you. One of, okay, so now do you want to continue the list, recompile in C++, use reference types, function overloads, going along and continuing our path to change? What would be next on the list? classes trying to repackage structures and related functions as a class with a public and a private access so uh because that does a much better job of defining the interface between the components in your system i think of all the features of c++ classes with access control is gets you a lot of bang for the buck and so if you're already familiar with doing object-oriented programming in c that transition is actually a pretty easy step. It's actually a relief, usually.
Starting point is 00:39:06 I mean, because I've done the whole object-oriented and C really object-oriented with strict APIs and function pointers to mimic class methods, and wow, that gets... Public and private headers, which never works right. No, that works fine. Oh, sorry. Opaque types. Opaque types.
Starting point is 00:39:29 Yeah. And so then you get to C++ and real classes. You're like, oh, that was a lot of work to implement something that's just a language feature. Exactly. I feel like, why are you doing all this to stay in C? Because you're basically acting like a C++ preprocessor in your code. language feature. Exactly. I feel like, why are you doing all this to stay in C? Because you're basically acting like a C++ pre-processor in your code. That's what I feel like sometimes when I see this stuff. It's like, I am a pre-processor.
Starting point is 00:40:00 I am a pre-processor. Just to stay away from C++, which is strange. So, yes, I find the whole notion of object-oriented C sometimes a little baffling. But when I did my Twitter poll, people had enormous number of reasons and variety of reasons for not switching over to C++. And we've covered a lot of them, so I'm not going to go through too much more. One of the ones I like, and I don't know if you agree with this or not, Dan, is I find it extremely useful for device drivers because if you use inheritance carefully, you can end up with device drivers which are interchangeable for different hardware. Yes.
Starting point is 00:40:36 And so your middle layers don't have to look any different. You can put in simulated hardware. I've used that in the past and found it extremely powerful. Yep, I agree. I often tell people to go look at the Adafruit sensor library. I don't love their interface because it's full of floats, and I think that's really inappropriate for 8-bit processors. But the idea of a sensor as an object and all of the things that go below it, whether it's a gyroscope or an accelerometer or barometer, temperature, whatever.
Starting point is 00:41:10 It's just an interface makes sense like that. But one of the reasons C programmers hate C++ on my Twitter poll involved multiple inheritance, which I've never used. I have. In Qt, yeah. You've mentioned that displays are much easier in C++. User interfaces. User interfaces.
Starting point is 00:41:34 They are because they're made up of objects, so it maps to object-oriented immediately. And inheritance makes a lot of sense when you have something like, or subclassing makes a lot of sense when you have something like, or subclassing makes a lot of sense when you have something that's a generic button class that you want to style in a slightly different way but keep all the same interfaces. So for UIs, it makes just a ton of sense. Yes, that is almost always the example that's cited of a legitimate use for multiple inheritance.
Starting point is 00:42:04 And outside of that, I don't think I've ever used it. What C++ features wouldn't you use in an embedded system? What wouldn't I? Well, I'm not sure that there's any that I'd say flat out I wouldn't use. It very much depends on your resource requirements. And I'm talking about both space and time. But there are certain things that I find myself using very rarely in embedded systems, and multiple inheritance is one. And related to that is runtime type information. Is that like an objective C where it will tell you the function name as a string?
Starting point is 00:42:53 What is runtime check? What is runtime? That is when you form type hierarchies. Let's pick the well-worn example of a hierarchy of geometric shapes where you have a base type, which is a shape. And then you say, and the different derived types are things like circle, square, and rectangle. And the type conversion rules in such type hierarchies is that it is safe to take a pointer or reference to any specific shape like a circle and convert that into a pointer to a shape. And the utility of that is that suppose
Starting point is 00:43:34 you write a function that computes the area of a shape and you can pass a pointer to any shape. So you can pass it a pointer to a circle, a pointer to a rectangle, a pointer to a triangle. And you can have one shape function that will work for any one of those, I mean one area function, which will accept any any shape. Now, so it's safe to convert a circle to a shape it's not safe in general to convert a shape into a circle or a shape into a rectangle because you might have a shape that actually is a circle and when you try to convert it into a rectangle now you've got a a type error at runtime and so it's generally discouraged and it's generally regarded to be a defect in your design if you find yourself having to convert in the wrong direction
Starting point is 00:44:32 but life being what it is computing problems being what they are sometimes it's a necessity and so what runtime type information does is it allows you to do a safe runtime query to say, I've got a shape here. Can you tell me, is it a circle? Or can I safely convert it to a circle is actually a better way to express it. And so it's an add-on to the capability of virtual functions. And I have found that I can't recall when I needed that in an embedded system. That does seem like it would make the code a little bloaty. Well, yeah, it does have run...
Starting point is 00:45:15 That's the sort of thing that does have a runtime overhead. And so what it does is it has the effect of making the runtime tables, the virtual tables, may increase in size. There's more data added to the table to support the runtime type information operations. And so that's a compiler feature? I can just turn it off on my compiler or just never make the call? The generally advised approach is that most compilers have a compile option, a compile switch to say, disable runtime type information for this build. handling. You may find that your particular compiler handles exceptions in a way that it's overhead that you'd rather not incur. And so I can't recall the last time I saw a compiler that didn't have a switch to say disable exception handling. I thought, I mean, when I first heard of C++ in the 90s, exceptions were like the cool new thing. Everybody should be using them.
Starting point is 00:46:28 Never used them. To me, they always just seemed like go-to statements, but that's probably because I do occasionally think in go-to statements. They do have a big benefit. Well, let me digress for just a moment. I want to go back to something, which is one of the complaints about C++ that also surprises I don't understand why the compiler is injecting a constructor call at this point. And it seems to me like it's overhead that I shouldn't have to pay for. So I don't want to go there. But the way I look at it is that constructors are functions that initialize things and destructors are functions that release resources after you're done with something and if you don't one of the most serious problems you can
Starting point is 00:47:36 incur most subtle errors you can incur in it in a system is failure to properly initialize you know probably uh lots of hours have been lost to people tracking down bugs and systems only to find up forgot to zero that thing out and constructors go a long way to eliminating that error and and once you understand c++ it turns out that you can pretty well predict when those constructors are going to be called it's very systematic and unsurprising once you see the paradigm and so i actually think that this is one of the the biggest advantages of using c++ for object-oriented programming is that not only do you get classes with access control, but you get automatic compiler-generated initialization. And it really effectively gives you guaranteed initialization. If you design a class and put
Starting point is 00:48:40 constructors in there, the users of your class have to go way out of their way to create an object that isn't properly initialized and so a major class of errors goes away but one of the problems with constructors is they run before main no they don't you can uh when you have objects which are local to a function the constructors will run when that function is entered if you never enter the function you never run the construction global objects yes they were global objects too yes don't look at me like that now with global objects the exact timing yes that that is a pragmatic problem for embedded systems where you want to have very fine-tuned ordering of initialization. Yeah, the GPIOs have to be initialized before the UART is initialized, before my debug log system is initialized. That's right.
Starting point is 00:49:44 Right. But there are techniques that you can use. One of them is to use something called placement new or new with placement, which is a way of manually invoking a constructor on uninitialized storage. And so for for global objects there are some useful techniques that can give you exactly the control over the ordering that you want um but yeah it's not quite as simple as we'd like it to be and for memory mapped objects it's a little trickier but i've got techniques for doing that too and um and i did write some columns on that for embedded.com now what i what i um what i wanted to bring up is that in that context you know so uh if you are using
Starting point is 00:50:35 constructors and destructors the big difference between a simple go-to um it's actually uh the equivalent would be the c set jump and long jump functions um which allow you to transfer control from one function to another um the problem is that if you use set jump and long jump in a c plus plus program and the long jump transfers control from one function to another function it could bypass the invocation of destructors you could wind up with a bunch of objects sitting on the stack whose storage was deallocated but whose destructors never ran and therefore you could get resource corruption and so the use of exception handling is a way to say i want the equivalent of a long jump i want to transfer just escape from this function to some handler somewhere and i want to guarantee
Starting point is 00:51:32 though that any objects that need to be destroyed will in fact be destroyed and so i i think exception handling it's actually a very good feature, and it's viable in many systems, but I still caution embedded developers, what you ought to do is write some tests. See how your compiler deals with this. Investigate what the overheads are, and then decide if you can utilize that feature effectively in your environment. If you can, it's the right way to go.
Starting point is 00:52:06 It's a more disciplined way to deal with error conditions. One of the other things about C++ is style, which I think is a huge can of worms. But I wanted to read what one of the Twitter people pointed me to. And no, I'm not using Twitter names because I'm protecting you. Trust me. C++ encourages you to write worse code than even C does. C++ is a language that speaks to the inner intellectual. The more C++ you know, the worse you become at working with others. First, because your particular dialects of C++ tend to isolate you. Second, because you sit in
Starting point is 00:52:51 an ivory tower that few can approach. This is a problem with all highly abstract languages. Now, if you replace C++ in that paragraph or in that rant for Hillary Clinton, it seems to still apply. So, that seems like it's all very much opinion and it was pointed to as fact. What do you feel is… Well, C is the blue-collar language. Sorry. Dan, what do you think about style and C++? Is it better or worse than C or just a little different?
Starting point is 00:53:28 Well, it clearly is a richer language. And the term I used before was it's more expressive. I like the idea that I can think certain thoughts and then write programming language statements which i think require less documentation to match the code up with the original thought it's more self-documenting if done well now the flip side you know the the dark side of that um picture is that, yeah, you can make a mess of stuff. That in the hands of somebody who is poorly trained or intent on being malicious or very asocial, yeah, you can get, it can magnify collaboration problems. And so, you know, I'm not going to say that people who have had difficulties with CPLIT, you know, there's a lot of cultural aspects to it. How did you learn? What is your learning style?
Starting point is 00:54:36 What is your collaborative style? And so it's not a, there's no right or wrong here. Well, I think it goes back, that particular... Rant? That was a mini rant. So, it's not a, I think other people may find that, yes, that some people do have an attitude of, well, this is the theoretical better way to do things. I can see where that attitude would develop, I guess. Well, as Dan was saying, having fresh out of college C++ proponents to a team of industrial seed who has to get things done it's more likely the team is going to win over the fresh-faced newbie oh i have a question i'm gonna go to the next question unless you really want to comment on the previous well what i I think the thing that I object to most in these discussions is the blurring of the social from the technical aspects. The problems that we have with managing teams with different senses of style and taste and different learning styles, instead of saying, yes, it's a management problem, it's a people problem, they say, no, it's because C++ is a bad language.
Starting point is 00:56:18 And that is the thing that I think is wrong. I think you can evaluate the language on its technical merits. You can look at examples and say, is this more expressive? Is this less likely to produce subtle bugs? How will it fare in a code review and things like that? Well, actually, that is a social question. But the questions of efficiency, both speed and space efficiency, and portability, those are technical issues. And when people have negative experience with C++ and blame the language, that's when I take exception to that. Some people have mentioned debugging and name mangling as being a reason not to use C++. I thought that was
Starting point is 00:57:07 all cleared up years ago. Do you have any comment, Dan? Well, I thought it was largely cleared up as well, but some embedded developers are saddled with some pretty old tools. There's that, yes.
Starting point is 00:57:25 You know, every so often you run into a project and you find out they're using a new tool chain from 1998 or something like that. Why? Because, well, it's the last one that worked for exactly that particular configuration that we're still supporting. Because we're still running Windows XP. That's right.
Starting point is 00:57:45 And that happens. But for modern compilers, I think the name mangling is largely a non-issue. I agree. I haven't seen it in a number of years. Not on any of the ARM processors I've worked on in the last three. Oh, actually, here's more style questions for you. Some of these are from me, because I snookered a friend into actually looking at C++ after he had a really exuberant reaction against C++. with a lot of discussion he went off and learned some my reasoning for him was that it isn't about you as a professional long-term industrial programmer what you're doing is moving to
Starting point is 00:58:35 c++ because it's easier for the babies it's easier for the newbies and so we would like to make it easier to learn to program in our systems. How are we going to protect our jobs if we let other people do stuff? If we let these teeny boppers in. Do you think that that's true? Do you think that it's easier for new college grads to come into a C++ system versus a C system? For an embedded system? Yeah. Yes.
Starting point is 00:59:12 No. Okay. I don't... I would have to delve into that question a lot deeper because I'm still having trouble wrapping my head around exactly what the issue is because the um for certain operations in a sense the map you look at your c source and you say now what is this doing at the machine level what registers is it touching what memory locations that sort of thing and it's it's generally a fairly direct mapping with c++ when you add things like classes and inheritance it's still pretty direct but not quite as overt as it is in c now
Starting point is 01:00:00 the the trade-off though is that when you're programming large systems, in C, the tools you have to define the relationships between components. As things get big, the thing that starts to burden you excessively is keeping one component separate from another how can i alter this component update it revise it and have confidence that i'm not going to break a whole bunch of other code because so much of a c program is is global data and public members of structures in c++ you have access control you have compiler level, hey, nobody else is touching this, and that the integrity of the interface is being preserved. So if I go in and I make changes to the layout of some private data, I have a much higher making the program more comprehensible asrelationships of components easier is catering to babies, I don't get it. It mostly came out of working with Arduino and Embed and how those are nominally platforms for beginners non-programmers and yet both are generally programmed in c++ because the mappings are very hidden from the beginners
Starting point is 01:01:57 and so they don't they don't know pin maps to register blah. All they do is say pin dot on or off. Right. And that hides some of the complexity so that they can get moving a little faster. Well, it's really, excuse me, I don't have a lot of experience with Arduino. My understanding is that it's mostly a learning platform. It's not a production platform, right? It's an art platform more than anything else it's a it is a learning platform one-off project platform it's not a shipping platform really no but people have built it into much much larger systems because it's a reasonable process or used for research you know robotics and things like
Starting point is 01:02:41 that where you're not building more than two or three that yeah that that was my impression okay so i'm sorry i didn't mean i just needed that clarification before you went on so i guess i guess the question is i saw your question two ways at least here one was you you were talking about people coming out of college with object oriented c++ experience is it easier for them to come into an embedded environment that uses C++? I didn't realize you were talking about coming from Arduino and embed, which I'd have to take issue with that because while they are C++, you know, effectively, that's not really part of,
Starting point is 01:03:20 it's not a big deal as part of the language. It's C++, but it's mostly procedural? No. No, in Arduino, if you get a shield, you usually end up with a class. You include the header file, and then you treat it like an object. So if you have the Wi-Fi class, you're using it like an object. Yeah, but are you making your own objects? Not often.
Starting point is 01:03:42 That's what I'm saying. No, because then you have to go out of sketch land and into C++ land and suddenly you actually know what's behind the curtain. So yeah, so me personally, I don't find that there's, I mean, I guess there's a familiarity that would be nice, but there's still a big gap. Fair enough. In embed, you're encouraged more to write things. Embed is just C++ as far as I remember. It is, and people use it with C, and yet if you search for blah, BLE module, you end up with a class because that just tends to be... Well, if you're extending Arduino, you write classes, I suppose. I was just surprised that the people I knew
Starting point is 01:04:25 who were getting into embedded systems were all, came from C++, not because of academics, but because that's where the quote, easy platforms were. But Andre from the Great White North, who was
Starting point is 01:04:43 the person that we convinced to read a C++ book in the last couple months, said regarding style, I'm finding that C++ has a style, whereas C is a cylinder of pureed worms, where consensus must be imputed by decree rather than by best practice. Pureed worms. Yeah, I had to quote that. Thank you, Andre. I'd like to bring up another point, which I didn't want to let it fall through the cracks. One of the attitudes, I think, that C programmers in embedded systems tend to acquire is this feeling that no matter how hard you try to write carefully written, even statically analyzed code,
Starting point is 01:05:40 you're still going to get bugs, nasty bugs you have to debug at runtime. But in fact, I think the culture is more dominated by people who say, oh, what the heck, let's just throw together the code, get it to compile, so we can get to the real work, which is debugging, which I think is an unfortunate mindset. Now, what happens is if that's your mindset towards c when you get to c plus plus all those nice features which introduce layers of abstraction get in your way actually get in the way of debugging that i hear that complaint a lot
Starting point is 01:06:18 is that it's just so much harder to debug this stuff and there's a cultural shift that has to take place you have to you have to stop thinking that the real work is debugging and start thinking that the real work is the coding that you have to take advantage of the type system and the access control to try as best you can to reduce the incident, to take things that would have been runtime errors and turn them into compile time or link time errors. Now, that doesn't mean you're going to get to the point where there will be no bugs. But then the other way to defend against that stuff
Starting point is 01:06:56 is through the careful use of assertion checks that you build into your interfaces, pre and post condition checks, so that these things are automated and you know if you have an expectation about the range of values for a particular input to a function you can now easily spot the places where that value can arrive inside the class interface and just put assertion checks to catch that stuff. And so you want to take a more rigorous approach so that you essentially try as hard as you can
Starting point is 01:07:32 to wean yourself away from debugging. Now, I live in the real world. This is aspirational. It's not something that you're necessarily going to achieve because sometimes those assertion checks come at a runtime penalty that you can't afford. But by the careful use of things like replacing parameters of an integer type with parameters of an enumeration type, you can actually turn what would have been a runtime error, a range error, into a compile time typing error. And then you don't need the runtime check at all. And you keep pushing in this direction,
Starting point is 01:08:10 and you find that, hey, I'm spending less and less time in my debugger. And the fact that C++ has these layers of abstraction that make debugging harder becomes less and less of an issue. But if you don't make that mental shift right you always say hey this c++ is a debugging nightmare that that is exactly what i wanted from you dan really was that about debugging that it is using c++ is different nobody is saying it isn't different but you know debugging can be really fun
Starting point is 01:08:52 keep smashing bugs is great until you realize you can't figure this one out and then it's all gone bad and if it turns out it's from an initialization error it could be weeks if you just don't or because your code isn't properly modular or or somebody's stepping on toes they shouldn't because they're violating a private-public access... This makes so much more sense to me. My idea that it's for newbies is not as good as it's easier not to debug. It's harder to debug, but it's easier not to debug and not,
Starting point is 01:09:26 it's harder to debug, but it's easier not to spend all of your time debugging is just, yes. Okay. I'm on board. Now that's my experience. I mean, that's, it's,
Starting point is 01:09:38 it's not everybody's experience, but that's been my experience. I think that it's a hard experience to get around because a lot of us did have bad experiences with C++ the first time we tried it after years of C, either because it wasn't portable yet or the compilers weren't that good yet. But it's been 15 years since I had that argument and was right. Now I'm afraid if I had that argument, it would not. Yeah, I would be on the side of C++ this time.
Starting point is 01:10:15 Chris, do you have any more questions? I have one final question, more of a request for a blessing. I often like to use the singleton design pattern for device drivers and things, and C++ makes that quite easy. I have heard that's a terrible thing to do. I would just like Dan to tell me either that I should go repent or that I should be allowed
Starting point is 01:10:37 to use it in certain cases. But what's your motivation for using the singleton? To avoid global objects i can't remember you only have one spy driver you i only have one yes i only have one device of a certain type and i want to make it available throughout the code without doing a lot of standing on my head passing it to objects and such. Yeah. I think that's the real reason for doing it is to get an assurance, an automated assurance
Starting point is 01:11:14 that you're only going to try to instantiate the object once because clearly if you have only one instance of that particular hardware device, you don't want somebody creating, declaring more objects of that particular hardware device you don't want somebody you know creating declaring more objects of that type and say hey i know i just added another port to my board by constructing another it's magic that's right um and you know the alternative is you wind up with two separate threads of execution thinking they both own the same resource or something like yes so i i think that using techniques like that are generally good approaches i mean there might be alternatives
Starting point is 01:11:53 that might satisfy you for example uh sometimes a mono state pattern might be a good alternative you know but but i tend to prefer, I think, the singleton. I'm furiously Googling that. The monostate? Yes. Yeah, the monostate actually allows for the appearance of multiple objects, but they're all mapped onto the same construct, and it only gets initialized once.
Starting point is 01:12:22 Oh, interesting. Okay. Maybe we should have spent time talking about design patterns, but... Well... Maybe next time. Oh, one of the other comments before I let you go, because I know I'm almost out of time here. One of the things people pointed out about C is that it has really stopped changing since, well, 1999, C99.
Starting point is 01:12:51 Or even before that, if you're Microsoft Visual Studio. Really? Yes. No, that was my problem. Visual Studio 13 has C99. but people don't know that much about c99 because the books seem to stop getting updated after c85 and they don't seem to know about the new stuff with c++ you mentioned classes being the way to go do you have any books that you'd recommend books on on learning c++ not necessarily for embedded systems but maybe without all of the fluffy stuff without all of the you shall use stl in all cases because i can't i can't afford that lambdas actually i think yeah
Starting point is 01:13:48 this is a deficiency see a lot of us learned to program in c by reading kern hannah ritchie yeah yeah and it is nice and concise it's very well suited for professional programmers if you have some understanding of programming picking this up as a good quick introduction to programming in c is it's pretty hard to beat and um unfortunately the corresponding book by bjarnes strostrup the c++ programming language is about four or five times yeah and and fairly daunting and um and now and the books that are more the size of kernahan and ritchie is there's a book called accelerated c++ by uh koenig and mu and but that book takes the approach of teaching the standard library components, vectors and maps and sets and things like that, in preference to using the more primitive data structures like arrays and pointers and structures, which is considered to be the modern C++ learning style and is very appropriate,
Starting point is 01:15:07 except in certain embedded cultures, the ones we've been talking about. And so there seems to be a gap. I'm not familiar with a book that is a KNR-level treatment of learning C++ in an incremental style, which I think is appropriate for a lot of embedded developers with existing code bases. I think it's just a, it's a whole. Now, that doesn't mean such a book doesn't exist, but I'm not familiar with one. That's fair um i will give a shout out to siddhartha rose sam's teach yourself c++ in one hour a day um which andre said went
Starting point is 01:15:57 through a nice logical method of here's a chunk here's a chunk without a lot of here's the whole style you must use at all. But if anybody else out there has a good C++ book, one that reminds you of K&R or Harbison and Steele for C, let us know. Maybe there is something out there we just don't know. Okay. Okay. It's been a long one, hasn't it? We needed something meatier after last week's giggle fest. Dan, do you have any last thoughts you'd like to leave us with? Only that I urge people to, in discussions of this sort, try very hard to separate out the technical issues of
Starting point is 01:16:49 language from the people, the management, the social issues of collaborative software development. And that I think that we can have a much more productive and informed discussion if people would be aware of how they keep blurring these lines and try to make every effort to separate this out and say, you know, here's what my concern really is, rather than attribute a people problem to a tool. Good advice. Really good advice. My guest has been Dan Sachs, the founder and president of Sachs and Associates. He was the columnist for the C C plus plus users journal, embedded systems design, and several other publications. He also served as secretary of the ANSI and ISO C plus plus standards
Starting point is 01:17:42 committee in his early years. We're honored to have him on. We're also honored that you gave us some more iTunes reviews and good stars. We appreciate it when you take the time to do that and to share our show with others. I'd like to send a special thanks out to Christopher Svek and Andre from the Great White North
Starting point is 01:18:01 as they helped me prep for this show. Thank you also to Christopher for producing and co-hosting. And thank you, of course, for listening. Hit the contact link on Embedded FM if you'd like to say hello or email us show at Embedded FM. You can use that address
Starting point is 01:18:18 to enter the favorite fictional robot contest where you can win a copy of my book or join iRobot. They're both good options. We'll be here next week. In the meantime, I have a couple of final thoughts to leave you with, because I did send out that Twitter message where I said, if you are an embedded programmer who primarily uses C, why don't you use C++? And I got so many good reasons and good tweets back. Even if I didn't agree with all of them, they were very helpful. My favorite of them all, though, came
Starting point is 01:18:53 from James Wack. Because of ignorance, I suppose, my knowledge of C is much more comprehensive, and I feel that I have more control over it. I thought that was the most honest, best reason. And now a quote from somebody a little more famous, Mahatma Gandhi. Live as though you were to die tomorrow. Learn as if you were to live forever. Embedded FM is an independently produced radio show that focuses on the many aspects of engineering. It is a production of Logical Elegance, an embedded software consulting company in California.
Starting point is 01:19:31 If there are advertisements in the show, we did not put them there and do not receive any revenue from them. At this time, our sole sponsor remains Logical Elegance.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.