What Makes C++ "Hard"?

Go To Last Post
186 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Greetings -

 

I realize that this is an open-ended question and I hope that it does not descend into a "flame war" because I really am interested in this.

 

Hypothesis: Many see C++ as a difficult language. Example, Cliff recently wrote (Multi-File C++ #21):

 

I've only been doing C++ for about 5 years now, give it another 5 and I may finally "get it"

 I see a couple of top-level possibilities:

 

1. The complexity of the language, itself

 

2. Poor teaching about the language (Johan, excepted!)

 

3. Poor understanding of the language by those who try to use it.

 

My hunch is that all 3 play a role. If the language, itself, is the biggest part of it (items 2 & 3 would appear to be driven by item 1), what is it about the language?

 

1A - Many users come from C background, and some things have to be unlearned

 

1B - There is often more than one "right" way to accomplish a task (but that is true of C, also).

 

1C - There are techniques that seem superficially similar but are enough different to cause problems (pass-by-reference vs pointers comes to mind)

 

1D - The whole Class structure and the idea of "instances"

 

1E - Inheritance

 

1F - The idea that some things can be "private" and others "public"

 

1G - The fact that ALL of the above are together in a single language (but VisualBasic and XOJO have most of these attributes and are not generally considered "difficult")

 

I would like to hear from folks who ARE C++ users: what have been YOUR stumbling blocks to effective use of the language? And, folks who have tried and given up: what caused you to give up (beyond the generic "Its just too hard").

 

Lets keep it civil!

 

Cheers,

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

 

for now I choose to stay away from posting in this thread. I could easily have a lot to rant about, but I'm sure I could absolutely kill all other participation in it by rambling away as I often do.. ;-)

 

Rest assured that I will follow/read the activity here. Having been a teacher of programming languages I am always interested in how "the learner at the other end" thinks and feels.

 

My staying away from posting might change if I find pure errors, or "blatant misconceptions".

 

As you where, Gentlemen!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Johan,

 

Totally understand your position. My interest is how "us mere mortals" deal/have dealt with it. I am sure that you will have some useful input, once some comments have accumulated.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Sat. Jul 8, 2017 - 05:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
I would like to hear from folks who ARE C++ users: what have been YOUR stumbling blocks to effective use of the language? And, folks who have tried and given up: what caused you to give up (beyond the generic "Its just too hard")....
I am a C++ user when a project absolutely requires it. Otherwise, I have found and try to promote labor saving alternatives.

- John

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And, what would those "labor saving alternatives" be? What about C++ pushes you to find labor saving alternatives?

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Sat. Jul 8, 2017 - 06:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll get back to this. I have quite a lot to say but not really practical using a mobile while I'm out walking a cat! I need QWERTY,

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who told you a language is hard if it takes 10 years to learn it?

 

JW (the C-hater -- I guess it makes me then C++ hater++)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jan, BRILLIANT link! Says it all really.
.
Oh and I'm intrigued he recommends Python as a first language. Couldn't agree more. Wish it had been around when I started!

Last Edited: Sat. Jul 8, 2017 - 07:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, this thread sounds promising, I'm trying to learn C++ myself. Not only is the language itself much more complex and powerful than C, but it's standard library is also much more complex than the one from C. So there is a lot to learn and this can be discouraging.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suggest that you should start with Arduino.   e.g. ready-made libraries and class methods.

 

You don't need to know much more than how to write simple expressions and statements.

Acquire familiarity with building examples,   adapting for your project.

Ask questions with your "code" or complete Arduino project.

 

If you want to learn C++ from scratch,   follow complete Tutorials on a PC.    Dig a big hole and bury your Arduino until you have finished the course.

 

I am surprised that any course would "start" with templates.     I would expect to learn how to use expressions, loops,  library class methods,  ... before you ever write any class of your own.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Clarification: My motive for starting this thread was to try to find out where others have problems so that I would know where to focus a bit more energy. Second motive was an attempt to NOT become discouraged, knowing that others also have problems.

 

That said, if you really prefer another language that has comparable power to C++, it would be really interesting to know what the differences are, that makes Language (whatever) easier (to learn, to use) than Language C++. Again, please keep it civil. I an NOT asking which one is "better". What I AM asking is about the "features" of C++ that make it challenging compared to other languages of comparable capability. Or, maybe visa versa! This fits with my initial motives because A/B comparisons help to clarify where the real problems are.

 

For example, I could see someone writing: C++ is hard because it shares so much with C (and sometimes it is hard to keep track of which feature goes with which language). But, what makes it easier to learn is that it shares so much with C.

 

Thanks, everyone!

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Sat. Jul 8, 2017 - 09:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm at the point where I only futz with Arduino and assembler, and assembler only for AVRs that cost less than a dollar.  Arduino is C++ with extensions and downloadable libraries.  In brief:

 

The libraries provide a way to interact the host AVR with all the various peripherals, sensors, and break-out boards available.  The main() code is split into two sections: the setup() and the loop().  This is called the '.ino' file and is where the user interface is developed.

 

An include statement for a header file "#include myNewToy.h" gets placed at the very beginning of the code.  This calls the .cpp file of the same name as the header file and compiles the source code of the library.  To use this library, the programmer calls the constructor method and instanciates an object in SRAM for the class that is defined in the .h header file.  This gives the strange code line:

MYNEWTOY someNewToy  myNewToy;   An object 'someNewToy' of class MYNEWTOY as be created in SRAM using the class constructor myNewToy(). 

 

At this point, in the .ino file,  the programmer can call methods that are defined in the class such as:  someNewToy.init();   These methods are for the device, peripheral, or sensor described in the library .h  and  .cpp  only.  The presentation, manipulation, and storage of data from the device is done by the .ino cover program.   Standard topics in C++ study like inheritance, overloading, perverse polymophisim and likenot are written into the library source code, should the author be up to it.   Ordinary programmers who are trying to get a microcontroller to do something useful to them can ignore these topics until they have advanced to the point where these topics need to be mastered.

 

-- I think that the problem with C++ books is that the authors are trying to scale the language from student test programs to big corporation info-systems.  C++ can do this in theory, but this should not be attempted in books for beginners.  But the authors always do that.  Another thing is that C++ book authors always assume that C++ learners already have a solid background in programming C or some other procedural language.  But Arduino users are often "the soldering iron has two ends-one is hot" type of beginners.  They don't need a discussion of inheritance, overloading, perverse polymophisim to get some LCD screen to print "ON" when a switch is pushed.

 

   My two-cents worth in electronics/computer programming these days is: if no one is paying you to master a topic, and you don't need to technically master a topic to get your vision into your application, then only learn a brief overview of the specific topic.  This goes contrary to the 20th century technical ideal of learn a lot about everything.  But there is too much technology in the modern age to follow this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if no one is paying you to master a topic, and you don't need to technically master a topic

Yep, and that's even more to the point if the government is subsidizing your living with a pension...... devil

 

I'm starting to do just fun projects now, no need to destroy more brain cells than necessary.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have no intention of trying to "master the topic". I do, however, want to be able to do a bit more than follow a recipe!

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One problem seems to be that C++ was designed to be lots of things, to different people, sort of  like PL/1.  (PL/1 was supposed to replace ForTran AND COBOL, but I'm pretty sure the programs produced by the ex-fortran programmers looked a lot different from the programs written by the ex-cobol programmers!)

 

That means that it supports multiple STYLES of programming, and there seems to be no end of people that are certain that your style is "NOT REAL C++."

This is especially true for embedded programming vs "big computer" programming.  For example, dynamic memory allocation (and the assumption that there is lots of memory to allocate) seems to be very "core" to a lot of C++ (or Java, or Python, or most any "object oriented" programming language), while there are large numbers of embedded programmers who think that it should NEVER be used.

 

I think Arduino did a reasonably good job of using some C++ concepts for an embedded environment, but I'm pretty sure that there are C++ programmers that are just APPALLED at some of the inconsistencies, design choices, and cavalier switching back-and-forth between C and C++ ("Why is Serial an object, but a PIN isn't?!"  "Why is "Serial", part of the top-level user API, NOT of a consistent type?")

 

There's a "half-joke" I sometimes make about being able to write C code in a dozen different (non-C) languages  (at least I forgot fortran!)

 

One observation I had is that C++ has some really strong advantages when you have "objects" that contain large amounts of compile-time initialized data.  This doesn't show up too much when programming microcontrollers, but if you ever contemplate setting up a a Windows GUI, with buttons and menus and such, in plain C, you might have a lightbulb go off...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't find surprising that C++ could take a decade to master. For example, I think I have a pretty good grasp of C, but then, when I realize this is possible:

 

int main() {
	if (*main == &main) (********main)();
}

... I think: "Much to learn, you still have."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Q. What Makes C++ "Hard"?

A. Because it was designed by Computer Scientists and not programmers.

 

Q.What Makes C++ "Hard"?

A. Because it was designed by committee.

 

Q. What Makes C++ "Hard"?

A. Because someone decided that OOP was a 'Good Thing' and what with C being the most popular programming language and all it was decided that C had to embrace OOP.

 

Q. What Makes C++ "Hard"?

A. Because for people programming microcontrollers it makes little sense to use it.

 

 

Michael Barr in his book 'Programming Embedded Systems in C and C++' has a section in the appendices called 'Limiting the Impact of C++'. If you dig around you can find a PDF of the book online. That section is an interesting read.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I'll break in..

Brian Fairchild wrote:
Michael Barr in his book 'Programming Embedded Systems in C and C++' has a section in the appendices called 'Limiting the Impact of C++'. If you dig around you can find a PDF of the book online. That section is an interesting read.

 

Not very "interesting" really. 2.5 pages where he essentially says

 

- Most OO features comes at no or a very reasonable cost

- Exceptions and Run Time Type Information comes with a (for small embedded systems) substantial cost

- Templates comes with a prohibitive cost - this is just wrong. Templates comes with no extra cost as compared to you yourself writing duplicate almost identical functions or classes

 

The whole treaty on 'Limiting the impact of C++' is less than 2.5 pages. The part about what to stay away from is one paragraph. The book is 18 years old. In this section Brian refers to is a sidebar about "Embedded C++", a 'standard' that never took off and now essentially a very dead thing.

 

Brian Fairchild wrote:
Because for people programming microcontrollers it makes little sense to use it.

I wonder what the people in the Arduino community would say about that..?

 

That's my take on Barr's treaty. I'll try to stay away again, so that us "politrucks" won't run over all you others..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you might have a light bulb go off...

So is this an OOPs moment?? surprise devil

 

http://footage.framepool.com/shotimg/qf/688959735-chauffe-eclater-eclat-de-verre-filament-courant-electrique.jpg

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Q. What Makes C++ "Hard"?

A. Because it was designed by Computer Scientists and not programmers.

A. Because it was designed by committee.

 Just because C++ is a huge language will lots of computer-science-y features added by committees, doesn't mean that you have to be an expert with ALL of it to be an effective C++ programmer...  (as is true of every other language.  Some pieces of languages shouldn't be used very often.  Others shouldn't be used with each other.  Still others can be badly mis-used if you aren't careful.  (Hmm.  I think I'd hire someone whom I was convinced wouldn't misuse features over someone who liked to use all the features all the time.  I had a classmate in college who proudly proclaimed on his resume that he had used seven different programs to generate it.  Shudder.  And there are the assembly language programmers that like to set up a set of macros that rename the typical opcodes to their preferred names ("goto" for the unconditional jump, for example.)  Just ... no.)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have often thought plain old 1970s era C was the perfect language.  It amuses me when others say that it is hard to learn.   I suspect a lot of that comes from the teaching notion that advanced things must be hard to learn.  A sort of circular logic that becomes self re-enforcing. 

 

The problem with computer language mutability is the need for a measurable number in work groups.  Why strong type defining is preferred by those who need to manage projects.  C++ is a perfect example of this.  It really needs a team of programmers and a top down design to implement the objects and structures.  Why C++ works in the processing/arduino environment.  The heavy lifting is done by the team.  The rest is like filling in the pages of a coloring book, or connect the dots drawing.

 

The other factor is the cost of the toolset.  I would often get frustrated that as a hobby programmer,  That I could not afford the current visual studio or library set.  Even Apple charged quite a bit for developer tools and different library sets. Often when I wanted to play about with something,  I had the wrong library revision.  This lead to my disdain for makefiles and other script and build tools.   I got even more frustrated with high level programming when I was attempting to move some of my C programs from mac OS 7/9 to mac OSX objective C.  That there was no simple way to access a pointer to an object by casting to it directly.  That one has to inherit the app structure to get the frameworks in which to attach things to.

 

I personally learned to program (rather than code) some 40+ years ago in the mid to late 1970s.  So I tend prefer a bottom up approach which is great for a single programmer.  I also have never been able to unlearn that pointers are ints and that ints are not 12 or 24 bits plus a bunch of flags.  Ironically I never had DEC hardware to program.  I did however have a lot of books to learn from.

 

The AVR became for me the perfect embedded environment as the ASM instruction set is pretty much pure C primitives.  I think there really are only something like 7 instruction concepts, that once learned allows one to program anything.  As I was first a sales support rep for a retailer (in the early pre-IBM PC 10980s)  I tended to program for fun on evenings and weekends.  I then went in to QA so still continued to program after hours.  This lead me to be more of a trial and error programmer.  I also took to reverse engineering other code to see how it worked, attempts to run Posix code on early OS 7 era mac's, not to mention porting windows programs to mac.

 

As for scripting chance would have it, that I learned postscript in the 1990s while working at apple.  I can lash something out in that language faster than other scripting tools.  Were I starting over it would probably be Python.

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I wasn't sure if my thoughts on this thread would make any difference, until these two sentences came up:

 

Brian Fairchild wrote:
Q. What Makes C++ "Hard"? A. Because for people programming microcontrollers it makes little sense to use it.

 

JohanEkdahl wrote:
I wonder what the people in the Arduino community would say about that..?

 

.......AH HAH!

 

The programming language IMNSCFO is as hard as you make it out to be based on what you learned first.  And in Johans reply to Brians observation, most Arduino users may not be programmers to begin with, just hobbyists who never moved past a 40-in-1 Radio Shack kit.  Then Arduino hit the stage and now there is something for the average schmoe.  And since it is C++ based and the target audience does not have much...if any experience programming then C++ is what they are learning as their first language.  So it's NATIVE much like their spoken language.  We have seen in threads here Arduino users that want to move over to the "other side" as some call it get frustrated with the C conventions.  It also has to do with how much effort one puts into the learning, and how open the mind is to it as well.  Forget what you know, as it will only get in the way.

 

I started with assembler, and had a tough time learning the basics of C, to which I am still learning....10 years for me would be a good realistic goal to be proficient enough that I wont second guess myself so much.  Same thing applies to whatever language you are learning, be it spoken or programming.  I would put a caveat that for some, learning another language may be quite easy, to others a struggle.

 

Cheers,

Jim

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One of the real "smart moves" with the Arduino programming system is that they (generally) do not call it C++. That seems to make it much easier, right there.

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, finally sat in front of QWERTY. So the thread started when I suggested C++ would take 10 years to learn. Let me put a bit of context around that remark.

 

I started programming about 40 years ago (well OK, a bit longer but in that ball park). For the first 5..10 years it was mainly a mix of BASIC (as most "home computers" had in those days) and the native assembler (because limited performance meant that you soon found that you needed to "delve into the guts" to get any kind of performance).

 

I then went to university and did (principally) 3 years of Pascal. (With experience of a few other things like FORTRAN, Algol68, etc). Pascal is a nice language and it teaches you structure, modularisation, strong types and so on.

 

When I started to work professionally it was supporting Z80 based home computers so everything I then did was back to BASIC (Dartmouth style) and Z80 Asm. Again I found I could achieve most using the assembler and concentrated on that. This carried over into subsequent Z80 based designs we made. We then started to make 8086 based "IBM compatibles" so in the absence of any sensible language (I don't count "GW Basic") I used MASM 86 to program most .com and .exe in 8086 assembler.

 

Finally colleagues working on non-PC projects in which they used C introduced me to the use of C. I guess that was the early to mid 90's. So 25..30 years ago. Slowly but surely I self-taught myself C. After 25+ years I think I now have a pretty fair grasp of C. As I have used almost every one of them at some point I have a good memory for pretty much everything in standard C library and know pretty much everything that <stdio.h>, <stdlib.h>, <math.h> and so on have to offer.

 

Similarly after all this time I think I know pretty much all the possible syntax available in C. I have read the whole of K&R about 3 or 4 times and I think, at various times, I have read pretty much everything contained in the ISO C99 standard. Having said all that I would say that about once a month there is a thread on Freaks (or a question I see on Stack Overflow or similar) that adds something new I still did not know about C.

 

But on the whole I think any one individual could carry the "whole of C" in their head (basically an encyclopedic knowledge of K&R) after maybe a couple of years of study and perhaps another couple of years of putting theory into practice. This is nice because it not only means you can carry the "whole toolbox" around in your head but it also means that given pretty much any piece of C code (except perhaps that which has been deliberately obfuscated) you can read and understand almost any code any other C engineer has written. After 4..5 years you could do this "competently", after a decade or two you could do it at expert level.

 

Then we come to C++. Where to start? As other recent threads have shown, even if you take just the "core" language facilities you are talking about fairly heavy books stretching over 1,000+ pages just to cover the "basics". (compare to C - my ANSI K&R has 261 pages before you reach the index). So even the core in C++ is 4 times more complex. To reach the point where you can read and perhaps even write using every tool in that particular box is bound to take you 3..4 times as long as it does for C. But that rather misses the point that C++ isn't really just about the "syntax". It's more about shifting your whole approach to design and implementation to make the best use of the modularisation it imposes. That aspect is far more difficult to grasp (for a dyed-in-the-wool C/Asm programmer) than just learning the convoluted syntax of the language. I may never be able to shake off my C programmer approach to design. Young people who do C++ first and are not tainted by C will find this much easier. Knowing C really is a barrier to getting the most from C++ (I see this in my young colleagues all the time!)

 

But it does not stop at this core either. For one thing C++ is a "moving target". It's very much a language still under development and there have been massive changes to the core at C++98, C++03, C++11, C++14, C++17 - you may start to spot a pattern there! So every 3 years there's a whole new bunch of stuff to add to your understanding. Also books consequently go "out of date" fairly rapidly. If you pick a book at Amazon is it 98, 03, 11, 14, 17 ? If you are lucky the author may have provided updates.

 

But as well as the core syntax there's also the question of library support. The libstdc++ is huge compared to libc. Sure you still have all your strcpy() and memcmp()s if you want them but you now have queue, array, vector, string, istream, ostream, etc etc. If you just take even one of those who can (off the top of their head) remember the syntax for iterating a vector for example? if you said:

  for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it)
    std::cout << ' ' << *it;

then well remembered!! But this is my point. I would suggest (certainly for anyone over 50 anyway!) there is now so much in the C++ Standard Library to be able to remember every method and every syntax without having to search and look things up every time. This also means you are often going to hit syntax when reading someone else's  code where your first thought is "what in the name of all that is holy is going on here?". You simply cannot carry the whole toolbox around in your head any more.

 

I spend a lot of my life not writing clean/new code but adapting existing code which may have been written by any one of about 50,000 C++ programmers in our company using any part of C++ so I may need to recognize anything that some very advanced C++ programmer may have used. In fact some programmer's seem to go out of their way not to write simple/clean solutions but to declare "look at me, see how clever I am, see this hugely obscure syntax I know about that you have probably never seen in your life, aren't I clever in being able to needlessly shoehorn it in to this?".

 

Oh and things don't stop there. I just checked a Boost directory I have:

 

 

So a fairly out of date copy of Boost is 5.4GB (true some of that is binary libs and tests) So if you are reading code where the C++ author has used additional facilities like Boost there's potentially 1,000's and 1,000's of other things you need to know about to be able to read the code. That tree contains 11,552 .hpp files for goodness sake!!

 

In fact the more I think about this the more I think there is no hope left in my lifetime to get to a point of having a reasonable familiarity of everything in C++. My comment about another 5 years is a huge under-estimate. I think all you can hope for is to get a good understanding of the core and be ready to just look other stuff up as you come to it.

 

It tickles me to see Amin asking for a summary of all this on 10 pages - no hope.

Last Edited: Mon. Jul 10, 2017 - 10:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am terrified by Jim's approach. There is no way that I could absorb C++ like that.
.
However, learning how to use Arduino libraries and writing simple sketches is VERY practical.
.
There is no point in knowing everything. Comfort and familiarity with common features and problems is adequate.
You might want to extend an existing library class. Or handle some hardware. In which case you study these particular aspects.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

So what we really need is C++-.

 

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
I am terrified by Jim's approach.

Which Jim?

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't need to know all of Java.   Or all of C++.  Or any language.    You DO need to know how to find documentation,  read it,  learn to use Libraries.

 

On the other hand,   C is small and absorbable.    But I still need to check the occasional syntax.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

But arguably you do need to know the whole of C++ to read and maintain the code of others. I'd say it is still daily I read pieces of C++ and see syntax/operation I don't recognise. I spend half my life on Stack Overflow looking things up! 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
You DO need to know how to find documentation,  read it

The awareness that this is even necessary - let alone the ability to actually do it - seem to be sorely lacking these days ...

 

frown

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes,  but you live in a different Universe to Jim.

 

Jim has his own projects and code.    He does not need to worry about video processing.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
you live in a different Universe to Jim.

Who? And which Jim?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

West Coast Jim,  Andy and I all live in a different Universe to Cliff.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

Well, since all "politrucks" but me are in anyway.. ;-)

Brian Fairchild wrote:
So what we really need is C++-.

You already got it. It's C++. Use what you want, need or are told to use. Don't use the rest.

 

If you need to enforce your subset, e.g. to control the JavaScript youngsters with their baseball caps backwards, then the document you need to write is called a "coding standard".

 

Most all of you advice against dynamic memory allocation in C in small embedded systems. Is that an argument for needing a C-? Of-course not.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Mon. Jul 10, 2017 - 01:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Most all of you advise against dynamic memory allocation in C in small embedded systems. Is that an argument for needing a C-? Of-course not.

+1

 

and many 'C' coding standards also advise against using various other language features; popular choices include

  • goto
  • trigraphs
  • ternary operator
  • the "optionality" of braces

 

 

(go on - who had to look up "trigraph" and/or "ternary operator" ... ? wink )

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

(go on - who had to look up "trigraph" and/or "ternary operator" ... ? wink )

 

I refuse to answer :-)  but what's "optionality" of braces?

 

JW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
(go on - who had to look up "trigraph" and/or "ternary operator"
Presumably those who haven't been doing C for 10+ years? ;-)

 

I guess a more pertinent question is "go on - who has ever actually USED trigraphs"?

 

(I'm pretty sure we all use ternary and probably quite regularly).

 

BTW my understanding of trigraphs was that they were for those who had limited keyboards without all the punctuation symbols - surely, since IBM AT (1986 was it?) and the 105/106 key keyboard that has not been the case for a VERY long time.

Last Edited: Mon. Jul 10, 2017 - 02:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW my understanding of trigraphs was that they were for those who had limited keyboards without all the punctuation symbols - surely, since IBM AT (1986 was it?) and the 105/106 key keyboard that has not been the case for a VERY long time.

I think it was IBM that blocked the removal of trigraphs from C++14 at least (think they're planning to remove them in C++17...)

:: Morten

 

(yes, I work for Microchip, yes, I do this in my spare time, now stop sending PMs)

 

The postings on this site are my own and do not represent Microchip’s positions, strategies, or opinions.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wek3 wrote:
what's "optionality" of braces?

I made the word up.

 

But what I mean is that 'C' allows, for example,

if( condition ) statement;

whereas many coding standards insist that you use braces:

if( condition ) {
    statement 
}

 

 

clawson wrote:
"go on - who has ever actually USED trigraphs"?

I think I may have ...

 

Or it might be that I just got caught-out by them?

 

my understanding of trigraphs was that they were for those who had limited keyboards without all the punctuation symbols

Yes - that is my understanding.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> many coding standards insist that you use braces

 

Ah, I see. Thanks, Andy.

 

Jan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
If you just take even one of those who can (off the top of their head) remember the syntax for iterating a vector for example? if you said:

 

for (std::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) std::cout << ' ' << *it;

 

then well remembered!!

 

One of the things I observe from people learning new stuff (and that I suppose I myself do) is not "systemizing" things, or trying to "see the/a system".  Without a "system" there is no place to hang up those pieces of concrete knowledge and details. And you'll have a hard time..

 

For most all programming languages there is such a system, and once you start to see it things get much easier. Now, "knowing" you Cliff, I'm surprised that the iterator for-loop setup is a problem. I can see for a newcomer to the language that it might be hard to see, but isn't the below similarity rather obvious??

 

 

Assuming start() and end() are rather obvious names, what is left as perhaps "clunky" is the

std::vector<int>::iterator

which is

  • In the std namespace (that's "bog standard", so not hard to remember, eh?)
  • the class vector (good descriptive name there!)
  • which happens to be a template class <> (as all the standard collection classes are) so we must tell that it is int's that are in the vector, and finally
  • get the inner class iterator from that (another well chosen name, IMO).

 

Any active C++ user with a few weeks or months under the belt knows that you refer to things inside a namespace with :: . (And since a class by definition is a namespace we get a hold of the inner class using the same mechanism.)

 

If you try to learn C++ without looking for "the system(s) that makes up the skeleton of the language" then I can understand that it is intriguing, overwhelming and very frustrating. But IMO that goes for any programming language. Some have little structure and system - sometimes because not much is needed (assembler) sometimes it's just a hack (I'll stick my neck out and say BASIC).

 

And for those that have not been taught the concepts (*) of collections and iterators there is of-course little point and even smaller probability that they will just memorize the syntax.

 


 

It was well observed somewhere above that C++ tries to cater for many uses. One single use case probably will not use the whole language repertoire, perhaps even not a majority of it! 

 

C++ also caters for many "paradigms", one of them being "Object Orientation". Others are e.g. our good old "procedural" (just plain old "functions and data"), "functional" (especially with the introduction of lambda expressions), meta-programming (relying on C++ templates) ...

 

You don't need to take all that in! But I argue that you will be well served by taking in

- Some non-OO stuff that is really good. Function overloading is one such thing.

- The basic Object Oriented features. At least "tiers one and two" : Encapsulation and Inheritance. I'd vote for Inheritance also.

- As I've pointed out elsewhere templates are often an alternative to error prone and hard-to-control function style macros.

 

All this is for small embedded systems, resource-challenged and running "on the metal".

 

(As soon as we move to a system that might be hosted, but at least is not severely challenged for memory (one of the "larger" ATmegas or SAM Ds for example) I might very well use parts of the std library, e.g. collections and iterators. Possibly also algorithms, e.g. sorting or searching.)

 


(*) - "Concepts". Now there's  a word you cant use in its general meaning for much longer when discussing C++!

 

One problem with the language is so big is that it "steals" many general/generic words and give them very specific meanings. I just have "a bunch of data". "Collection"? Nope, taken. I want to talk about some flow of code with someone. "Algorithm"? Dangerous, since there are such in the std namespace. Etc.. 

 

The things that is around the corner is ... "concepts". Not quite clear on it yet, but it seems to be a way to put constraints on e.g. templates so that they fulfill certain "meta-properties". The run'o'the'mill example seems to be 'comparable'.

 


 

Anyway... It's a huge language. And it's growing.

 

C++17 was "frozen" this spring. Next up is C++20. Bjarne, Herb Sutter and the others seems to have spare time, but it looks like Scott Meyers gave up or just got tired.. (When will GCC support D for AVRs? ;-) )

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Now, "knowing" you Cliff, I'm surprised that the iterator for-loop setup is a problem.
More than anything it's probably remembering that the two methods involved are begin() and end() in fact!

 

I wasn't citing this example per se - just that there are 10,000's of things like this you need to remember to be able to either freely write this stuff or to understand what's going on in code you come across and try to read.

JohanEkdahl wrote:
which happens to be a template class <>
I think most of the "hard bits" I come across are use of templates. I understand the concept but there's something about the syntax that floors me most times.
JohanEkdahl wrote:
One single use case probably will not use the whole language repertoire, perhaps even not a majority of it!
Just did a "dir *.cpp /s" on one of our active source trees:

and for .h:

So a combined total of about 150 Megabytes of source. I'd say there's quite a lot of potential for a lot of the aspects of C++ to have been used there. (and that was ONE project tree).

 

Here's another one (actually perhaps one that I spend more time "engineering"), .cpp:

and the .h for that:

(so ~220MB of source).

 

These are projects written by 200..300 (perhaps more?) engineers so there's the potential the for every last type of C++ craziness to have been used at some point!

 

I could find 50 more projects of similar size without trying to hard.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I hope that casual readers, if there are any, don't get turned off by all this because I find it very enlightening. From several angles:

 

1. Seasoned programmers admitting that they have "trouble" with some of the features. That makes it much easier for us mortals who struggle with even the basics. 

 

2. There appear to be points where the experienced folks don't agree, to varying degrees, on how something does work, should work, is used, and so forth. This must certainly be one of the things that makes C++ "hard".

 

3. There are a number of features that the basic tutorials do not even attempt to explain, or explain incompletely, or introduce without much explanation, at all. So far, in the cplusplus.com tutorial, templates are one of those. Without this discussion, I would not have even known that this is the case!

 

4. The discussion has provided a great insight (to me, at least) into the challenges of learning even the basic concepts of C++. For that, I thank everyone who has contributed. My goal, as I think I wrote above, is to learn it well enough to be able to a little ways beyond cookbook coding. I have no illusions about expert level coding. My future life is not long enough for that, I fear :) And, I have too many projects in the pipeline to devote all my time and mental capacity to such an endeavor!

 

I am puzzled, a bit, though, about this "different universe" (item #31).

 

Cheers and Very Best Wishes,

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

Last Edited: Mon. Jul 10, 2017 - 06:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What makes C++ so difficult (at least for beginers)? According to the Kate Gregory, it's C. If you start teaching some 5days introduction into the C++, whenever you mention pointers, index operator and so on, you have to take a looooong introduction into the C part of C++. And understanding pointers is not so easy.

 

Whole CppCon 2015: Kate Gregory “Stop Teaching C" video: https://www.youtube.com/watch?v=YnWhqhNdYyk

 

It doesn't mean you don't have to learn poiners and some difficult stuff, but you don't have to do it at the start.

 

 

BTW: I already knew what digraphs and trigraphs are, but never used it (except for the check if they're really working).

Computers don't make errors - What they do they do on purpose.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
3. There are a number of features that the basic tutorials do not even attempt to explain

Surely, that is in the very nature of basic tutorials?

 

A "basic" tutorial is, by definition, one which does not cover the "advanced" stuff!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For those of us who are new at it, I find it really hard to tell what IS basic and what is "advanced". As introduced in the tutorial, templates seem like an eminently sensible idea but as I see the discussions above, it appears that the implementation is MUCH more challenging. Until this discussion, I could not tell if it is a basic feature or not! Vectors and iterators were things I had not even heard about (yet) so I put those in the "advanced" bin right away. Just like trigraphs and ternary operators in C (!) [Saw ternary operators used in FatFS and had to look them up to understand what the code was doing - first and probably last use].

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
I find it really hard to tell what IS basic and what is "advanced"

 

Yes.

 

That is why I repeat - over and over - this "firsts list:

 

Non Object-Oriented stuff:

- Function overloading

- References (v/s pointers)

 

The two first of the three pillars of Object Orientation: 

- Encapsulation, aka plain old classes.

- Inheritance.

- Polymorphism, aka "virtual functions.

 

And the "plain old classes" in itself is a biggie! (E.g we haven't started talking about the Copy Constructor yet, but it is important. And there's more..)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And that list is where I am putting my energy. 

 

Thank you for the enthusiasm that you have added to this. And, your patience! 

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
For those of us who are new at it, I find it really hard to tell what IS basic and what is "advanced".

Also not specific to C++

 

Witness the number of beginners here trying to start out on a USB project ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
Seasoned programmers admitting that they have "trouble" with some of the features.

Any day I work with C++, I look things up. It's normal.

 

ka7ehk wrote:
There appear to be points where the experienced folks don't agree, to varying degrees, on how something does work, should work, is used, and so forth.

This is true for all programming languages I know and have used for the last 25 to 30 years. I certainly is true for C. And for e.g. Java and C#.

 

clawson wrote:
More than anything it's probably remembering that the two methods involved are begin() and end() in fact!

When memory fails the IDE/editor should remember. "Intellisense"/autocomplete.. (I've been doing Java lately, and C# before that, and the first thing you do when you're not sure of the name of a method, or if it even exists, is to type <variablename><period> and then start scrolling and browsing the list..)

 

 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Witness the number of beginners here trying to start out on a USB project ...

 And I still consider TWI as "advanced"!

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KIIV_cz wrote:

What makes C++ so difficult (at least for beginers)? According to the Kate Gregory, it's C. If you start teaching some 5days introduction into the C++, whenever you mention pointers, index operator and so on, you have to take a looooong introduction into the C part of C++. And understanding pointers is not so easy.

 

Hah!  Understanding pointers is easy.  they are simply 24 bit ints with a bunch of flags for a total of 32 bits :>} The problem started when the managers and others started stating pointers are not ints.  Well technically they are unsigned 32 bit longs.  On some architectures the address registers were only 16 bits so pointers were 16 bits.   Now a days there are 64 bit pointers, although I doubt anything as that much dynamically addressable address space.

 

Typically a pointer points to an 8 bit "value" often called char in C.  This makes it easy to manipulate strings as there is a one to one mapping between an array of chars [] and a *char.

 

In the old days you just added one to a pointer to move the index.  Or subtract one to move it back.  Most people who were programming C learned ASM first.  This is the way ASM works.

 

As things got more complex one wanted to point to say 16 bit quantities rather than text quantities or more often to floating point structures.  in this case a 16 bit number is an array of size 2 or char int[2];  Now we have a new type called int which represents a number.   The confusion happens because a pointer (the 24 bits plus flags) *char only knows how to address the first 8 bits.   The construct *int knows that the value is 16 bits  so that char++ adds 1 to the pointer (ignoring the flags) and int++ adds 2 to the pointer.

 

As it is hard to remember how much gets added to the pointer,  C compilers maintain an internal identifier called size_t which tells the compiler how to map pointers to to address registers.   At this point thing could not be simpler.   Works the same as ASM.

 

Where things get more abstract (but are still simple.) is when blocks of memory contain a lot of different data.   C calls this a structure.  Now the compiler needs to know two things,  the offsets inside the structure and the size  of the structure.  AVR ASM has this built in as there are index registers which can offset by a simple number.  If for example a structure is a mailing address, such as name, street, city  then  theses become simple numbers that get added to the base pointer.  Adding the size_t of the record to the pointer advances one record, keeping the entry the same.  It is quite simple, but it is an unbounded infinity as records can contain other records or pointers to other records or sections of executable code.

 

Note that I left out type casting and memory management. These are implied in the pointer.  What the flags bits are for in the pointer.  These are hidden from the user and dependent on the implementation.   Dynamic memory allocation is a subject in and of itself as memory chuncks can be locked, relocatable, on the stack etc.  

 

With ASM and C one can have weak type casting as a pointer can point to anything in the memory space including code.   C++ is just a way to structure these allocations so that one does not have to keep a table of index offsets in ones head.   Sadly they got it too abstract.  Had they stuck with object structures, it would be fine.  Operator overloading, name spaces and that funny stuff with redirected IO instead of calling functions is where things get messy and the arguments get circular as are such concepts advanced features? or a simpler way to learn to "code."

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is a discussion going on on LinkedIn at the moment (https://www.linkedin.com/groups/... )

 

Here's one of the more interesting comments (from someone who seems to have a lot of strong opinions on the matter.)

 

Matt Heck: For microcontrollers _specifically_, as opposed to general embedded systems, I recommend C++ but without template usage. This is traditionally known as "C with classes", and the academics and architecture astronauts will roll their eyes at it. IGNORE THEM. This is an EXTREMELY effective approach for developing reusable, maintainable, extensible, _debuggable_ code for compact targets.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, can I ask incredibly noobish question about C++ here? I'm trying to learn it to, but just in very mild doses.

 

For example, this operator overload stuff is quite interesting. Here is some code:

 

#define OP <<

typedef struct {
	char a;
	char b;
} pair;

void operator OP (pair &l_arg, const int &r_arg) {
	l_arg.a = (char) r_arg;
	l_arg.b = (char) r_arg;
}
int main() {
	pair test;
	test OP 2;
	return test.b + test.a;
}

 

So, this struct has a pair of chars, and with the overloading, I can use any operator do to whatever, in this case load both char with the same value. Neat. Problem, is, it doesn't work with the "=" operator, why? Compiler complains that it must be a "nonstatic member function". Needs to be inside a class, I suppose, but why?

I didn't want to use classes yet, just graft some useful C++ stuff into plain C.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

awneil wrote:

(go on - who had to look up "trigraph" and/or "ternary operator"

 

Presumably those who haven't been doing C for 10+ years? ;-)

 

I guess a more pertinent question is "go on - who has ever actually USED trigraphs"?

 

(I'm pretty sure we all use ternary and probably quite regularly).

 

BTW my understanding of trigraphs was that they were for those who had limited keyboards without all the punctuation symbols - surely, since IBM AT (1986 was it?) and the 105/106 key keyboard that has not been the case for a VERY long time.

 

I have used trigraphs in the 90's , when doing C on an IBM Mainframe running MVS.

And the DK version of a 3270 EBCDIC keyboard didn't have ie. {} or []

 

/Bingo

Last Edited: Tue. Jul 11, 2017 - 04:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

@El Tangas: You already are using classes (in disguise). In C++ structs and classes are the same (except for a minute detail).

 

I'm not sure why you chose to overload <<, and then hide that behind a macro "OP"?

 

What you are doing is an assignment, so why not overload the natural choice of operator (i.e. =)? So (sketchy, untested!):

 

class Pair {
public:
  // Some constructors will come in handy..
  Pair()
    : a(' '), b(' ')
    {}

  Pair(char a, char b)
    : a(a), b(b)
    {}

  // Here's the operator overloading!
  Pair & operator = (const Pair & source) {
    a = source.a;
    b = source.b;

    return *this;
  }

private:
  char a;
  char b;
};

Usage:

  Pair p1('X', 'Y');
  Pair p2;
  p2 = p1;

 

There might be hard "technical" reasons for the = (and <<) operator(s) to be class members but I don't know off hand of any such. But anyway it makes sense that in any case where an operator alters an object the operator is a member of the class. Just like a when function modifies some member variable value in a class that function should be a member of the class.  The term is "Encapsulation". Keep data and "procedure" together in one place, the outside world ignorant of how it is internally implemented. 

 

EDIT: In general, whe n objects become more than "trivial", it makes sense not to do a lot of copying when the user does something like

p1 = p1;

so..

  Pair & operator = (const Pair & source) {
    if (this == &source) {
        return *this;
    }

    a = source.a;
    b = source.b;

    return *this;
  }

I will not get surprised if someone chokes on those &'s and *'s   ;-) 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Tue. Jul 11, 2017 - 05:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Problem, is, it doesn't work with the "=" operator, why?

 

Sure it does, if you set it up right; it should only take one argument, and returns a result...

Here's a copy of one of the Arduino functions:

 

String & String::operator = (const String &rhs)
{
	if (this == &rhs) return *this;
	if (rhs.buffer) copy(rhs.buffer, rhs.len);
	else invalidate();
	return *this;
}

(ooh.  This is the kind of thing that needs to go in a cheat sheet...)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:

El Tangas wrote:
Problem, is, it doesn't work with the "=" operator, why?

  Sure it does,

I believe what El Tangas is trying to say is "problem is, it does not work outside a class". (And no, it does not.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW, the operator overloading I did above does the same things that the compiler would provide in the default version - just so no-one gets stuck wondering what it "contributes".

 

Also, the technically correct term is "the copy assignment operator". When you do overload of that you should overload the copy-constructor at the same time. The copy constructor is used e.g. here

 

Pair p1('X', 'Y');
Pair p2(p1);  // <-Copy cunstructor gets called here!

An implementation of the copy constructor corresponding to the copy assignment operator in #57 would go:

 

class Pair {
   .
   .
   .
   Pair( const Pair & source) {
       a = source.a;
       b = source.b;
   }
   
   // ... or, using the initializer list instead:
   Pair( const Pair & source)
     : a(source.a), b(source.b)
     {}
   
   .
   .
   .
}

No need to check for self-assignment in the copy-constructor, since you (of course) aren't allowed allowed to

 

Pair p3(p3);

 

And as for the copy assignment operator, the copy constructor implementation above is what the compiler supplies as default.

 

More on both copy constructor and assignment operator here: http://www.cplusplus.com/article...

 

 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks guys, since I know so little of C++, it will take a while to analyze your posts... Probably I will have more questions latter.

 

Edit:

JohanEkdahl wrote:
I'm not sure why you chose to overload <<, and then hide that behind a macro "OP"?

Oh, this was just to test a bunch of operators with a bit less typing. When I tried "=" it gave that error I mentioned, I didn't even notice the "=" operator has just one argument. Why is that anyway, if "=" has 2 sides, source and destination?

Last Edited: Tue. Jul 11, 2017 - 10:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

1. Seasoned programmers admitting that they have "trouble" with some of the features. That makes it much easier for us mortals who struggle with even the basics.

Oh, I've seen many professional programmers struggle even with C. I mean basic stuff, like pointers.

 

e.g A colleague was sure there was a compiler error, because his function returned false even when the strings were the same:

 

bool test_string(char *str1, char *str2)
{
  if (str1 == str2)
    return true;
  else
    return false;
}

 

After I explained about pointers, he said he was sure that was not the problem, because he tested it and it worked. His test was :

 

  if (test_string("fred", "fred"))
    DEBUG_PRINT ("same\n");
  else
    DEBUG_PRINT ("different\n");

That may well return true, because the compiler puts identical strings into a common pool, so they have the same address. After all that, he seemed to accept my explanation, but offered the excuse "I've never really used strings before". That is what I would consider totally basic stuff for a professional C programmer. Now imagine how he got on with C++ ...

 

Complexity is quite hard to define, but a rule of thumb might be:  "number of ways unique elements can be combined." In the worst case, that is N ^ 2 where N is number of unique elements (assuming all elements can be combined with any other).

 

Another dimension is levels of abstraction, which is even harder to define. It is very dependent on the individual, some will say abstraction makes things simpler, because the same abstraction can apply to many instances, others say it just makes things harder to understand, because it moves one step away from the details. Levels of abstraction is similar to "algorithmic complexity". E.g. the sequence (0,1,4,9,16,25,36,...) can be expressed simply as n^2, where n is Positive integer. n^2 is more compact, so could be considered "simpler",  but you need to understand the abstraction.

 

C++ contains more language elements, has more ways to combine them, and introduces several new levels of abstraction. By that measure, it is certainly more "complex" than C. Whether that complexity is easy to understand or not, really depends on the programmer.

 

Bob. Engineer and trainee Rocket Scientist.

Last Edited: Tue. Jul 11, 2017 - 11:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

donotdespisethesnake wrote:
C++ contains more language elements, has more ways to combine them, and introduces several new levels of abstraction. By that measure, it is certainly more "complex" than C.

I really like that way of looking at it!

 

One remedy to complexity is what is sometimes called "orthogonality (of the language, in the broad sense)". I.e. patterns (oops, dangerous term, not intending "Design Patterns" here) are the same. It's when you can go "Well, if it worked that way there, then I suppose it should be this way here". E.g. see my figure above comparing a simple integer-indexing loop with one using an iterator.

 

Once you "break through", there is quite a lot of orthogonality in C++.

 

Before you "break through", it's another story..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In my research on C++ references, I learned that this allows assigning values to function calls. I find this very interesting, it's like you can use the compiler as a kind of macro preprocessor (I hope this simplistic comparison doesn't offend C++ experts...).

 

So here is a rather useless test program I wrote. But this certainly has potential even for MCU programming.

 

enum port_label {B, C, D};

volatile uint8_t & Port(port_label t){
	switch (t) {
		case B:
			return PORTB;
		case C:
			return PORTC;
		case D:
			return (volatile uint8_t &) PORTD;
	}
}

int main (void) {
	Port(B) = 0xFF;
	Port(C) = 0xFF;
	Port(D) = 0xFF;
}

This assembles to:

int main (void) {
        Port(B) = 0xFF;
  7a:   8f ef           ldi     r24, 0xFF       ; 255
  7c:   85 b9           out     0x05, r24       ; 5
        Port(C) = 0xFF;
  7e:   88 b9           out     0x08, r24       ; 8
        Port(D) = 0xFF;
  80:   8b b9           out     0x0b, r24       ; 11
}
  82:   80 e0           ldi     r24, 0x00       ; 0
  84:   90 e0           ldi     r25, 0x00       ; 0
  86:   08 95           ret

So this feature o C++, at least, doesn't seem to introduce any kind of special bloat.

 

Edit: there seems to be an implicit cast from type to type& in situations like this, I left it explicitly in the code for PORTD, so I don't get confused by this.

Last Edited: Tue. Jul 11, 2017 - 08:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:
Edit: there seems to be an implicit cast from type to type&

Don't think of references as pointers. While there is a definitive type difference between

SomeClass anObject

and

SomeClass * anObjectPointer;

i.e. the anObject and the anObjectPointer is of distinctively different types, this is not true for references.

 

Think of references as alternative names (dare I use the term "alisases"?) for variables. So with

SomeClass anObject;
SomeClass & anObjectReference = anObject;

the anObject and anOBjectReference are of the same type.  This is also hinted at by the fact that access to members through anObjectReference is done the same way as through anObject:

 

  Pair p1('X', 'Y');

  Pair & p3 = p1;
  p3.a = 'Z';
  
  printf("%c\n", p1.a);  // Prints 'Z'

 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Tue. Jul 11, 2017 - 10:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So here is a rather useless test program I wrote. But this certainly has potential even for MCU programming.

But you can do almost the same thing in C, though it's somewhat uglier (but also less mysterious?)

enum port_label {B, C, D};

static inline volatile uint8_t * Port(enum port_label t){
	switch (t) {
		case B:
			return & PORTB;
		case C:
			return & PORTC;
		case D:
		    return (volatile uint8_t *) & PORTD;
	}
}

int main (void) {
	*Port(B) = 0xFF;
	*Port(C) = 0xFF;
	*Port(D) = 0xFF;
}

 

(I actually had quite a bit of this sort of problem.  People would enthusiastically point out some object-oriented THING you could do in C++, and I would be "but I'm already doing that in ordinary C; why do I need a new language?"  Of course, the C implementation was a bit weird, and typically hid some ugliness inside C macros, so arguably C++ did have advantages.  At the moment, people seem to be all excited about "lambdas", and I'm thinking "pointers to functions; big deal.  Except now you don't have to explicitly write the function you're pointing to.  Which is good because...  because ...  ??  Because the "obfuscated c++ contests" can get even more mysterious entries?")

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting, I had no idea you could do that in C blush

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
At the moment, people seem to be all excited about "lambdas", and I'm thinking "pointers to functions; big deal.  Except now you don't have to explicitly write the function you're pointing to.  Which is good because...  because ...  ??  Because the "obfuscated c++ contests" can get even more mysterious entries?")

Because lambdas have access to all of the containing function's variables, so you don't have to pass them to the function as arguments (which can be unwieldy if the lambda needs access to a lot of the parent function's variables). It's unfortunate that C++ doesn't support closures, though, because those are really cool.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Has anyone tried an "Obfuscated C++" competition, or would that just be a little bit too rude?  S.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
People would enthusiastically point out some object-oriented THING you could do in C++, and I would be "but I'm already doing that in ordinary C

People often don't understand (or overlook) the difference between an object-oriented approach to design/programming (which you can do in 'C'), and having an actual object-oriented language (like C++).

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:

 case D: return (volatile uint8_t *) & PORTD;

I'll bite - why is the D case different to B and C ?

 

Oh and back at:

int main (void) {
	Port(B) = 0xFF;
	Port(C) = 0xFF;
	Port(D) = 0xFF;
}

Mt main question here would be "why?". Why not simply write:

int main (void) {
	PORTB = 0xFF;
	PORTC = 0xFF;
	PORTD = 0xFF;
}

or is this so you can:

int main (void) {
	Port(rand() % 2) = 0xFF;
}

or something ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

or is this so you can:

int main (void) {
	Port(rand() % 2) = 0xFF;
}

or something ?

 

I'm just testing possibilities, stuff that could be hypothetically done with the languages, since I want to know more about C++ and C. What you wrote would be an example.

 

clawson wrote:
I'll bite - why is the D case different to B and C ?

 

This one will require more explaining. Recalling the C++ code:

volatile uint8_t & Port(port_label t){
	switch (t) {
		case B:
			return PORTB;
		case C:
			return PORTC;
		case D:
			return (volatile uint8_t &) PORTD;
	}
}

As you know, PORTx are of type (volatile uint8_t), while the function returns (volatile uint8_t &). In my opinion, C++ is doing a cast implicitly here. I made it explicit in the last option just as a reminder.

 

In the C equivalent, it's different:

 

static inline volatile uint8_t * Port(enum port_label t){
	switch (t) {
		case B:
			return & PORTB;
		case C:
			return & PORTC;
		case D:
		    return (volatile uint8_t *) & PORTD;
	}
}

That is, &PORTx are already of type (volatile uint8_t *), so nothing is happening behind our backs.

Now, for the part I have doubts. In , Johan said:

 

JohanEkdahl wrote:

Think of references as alternative names (dare I use the term "alisases"?) for variables. So with

SomeClass anObject;
SomeClass & anObjectReference = anObject;

the anObject and anOBjectReference are of the same type. 

 

However, check this program:

typedef struct {
	char a;
	char b;
} Pair;

uint16_t & Set(Pair *p){
	return (uint16_t &) *p;		//OK
	//return (uint16_t) *p;		//Not OK	
}

int main (void) {
	Pair test;
	Set(&test) = 0x1020;
	return test.b;  //Will return MSB (0x10)
}

The commented out line can not be used, therefore  the types (uint16_t) and (uint16_t &) are different. Right? Just asking.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:
The commented out line can not be used, therefore  the types (uint16_t) and (uint16_t &) are different. Right? Just asking.

Possibly. Need to check. Will be back..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After a very quick read of some content on The InterWeb, it seems that references are (at least in a technical/theoretical sense) of different a different type than the variable it references.

 

But, as far as I know, for all practical purposes you don't need to typecast. As in my example earlier there is no need to typecast to do

 

SomeClass anObject;
SomeClass & anObjectReference = anObject;

A common explanation of what references are is "alternate name" or "alias" (the latter being somewhat dangerous to use without being very clear about it, since "aliasing" is a term that has another meaning and other implications).

 

Will look around a little more to see if there are any "complications" when using aliases in type hierarchies.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't have time right now to read all the responses so I might be duplicating.

 

I've been writing C/C++ for well since '95 so 22 years, programming for that + 10 or so

Is C++ hard? Well it has a lot of depth.

 

Dancing is a hobby of mine, the waltz is a simple dance, but it has incredible depth.

I can teach you the basics in an hour. You'll never learn it all.

 

C++ is the same.

At the shallow end it's basically C with better type checking.

At the deep end it's templates and objects and huge libraries.

 

Libraries are far more complicated than any mere language, when you add MFC, STL, Net, Linq etc you are out of the C++ world and into the library support. Don't blame the language for that

 

The one place where C++ has real issues is interfacing to C. especially callbacks / function pointers. There's just no clean way to handle a function pointer in C++.

if you are in PURE C++ you can do things that work, but if you call a C lib that wants a callback, it gets messy fast.

 

 

My latest project is 100% c++, all the interrupts, event driven state machines, serial IO, all C++. All written from scratch :P

FWIW, the coolest use of C++ I've seen is a templated ring buffer. it can take any type, builtin or custom with zero coding.

Works every damn time.

You want a uint8_t ring buffer, 1 line of code to create it

You want a ring buffer that takes your custom objects, again, 1 line of code. poof done.

 

Another great thing about C++ is data hiding, all you private data is private, the outside world doesn't even see it. No more structs being passed around and getting corrupted by jimmy the intern ( Peter the principal engineer)

 

C++ is not too hard, you're too weak.

 

Keith the Klingon programmer

"You have insulted my code. Prepare to die"

 

Keith Vasilakes

Firmware engineer

Minnesota

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

He hasn't taken the red pill yet, hes still in the C Matrix.

Templates do not, on their own, cause problems. People misusing templates cause problems.

 

westfw wrote:

There is a discussion going on on LinkedIn at the moment (https://www.linkedin.com/groups/... )

 

Here's one of the more interesting comments (from someone who seems to have a lot of strong opinions on the matter.)

 

Matt Heck: For microcontrollers _specifically_, as opposed to general embedded systems, I recommend C++ but without template usage. This is traditionally known as "C with classes", and the academics and architecture astronauts will roll their eyes at it. IGNORE THEM. This is an EXTREMELY effective approach for developing reusable, maintainable, extensible, _debuggable_ code for compact targets.

 

Keith Vasilakes

Firmware engineer

Minnesota

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Keith how ate you doing interrupts in C++. Presumably ditching the ISR() mechanism the CRT provides?
.
The issue is that very thing you mention - trying to get a pointer to a function "inside" a class (so it kind of has to be static )

Last Edited: Wed. Jul 12, 2017 - 06:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

keith v wrote:

FWIW, the coolest use of C++ I've seen is a templated ring buffer. it can take any type, builtin or custom with zero coding.

Works every damn time.

You want a uint8_t ring buffer, 1 line of code to create it

You want a ring buffer that takes your custom objects, again, 1 line of code. poof done.

Yup. I used that as an example just the other day. In another thread - so re duplicating, as far as I'm concerned you're off the hook..

keith v wrote:
Dancing is a hobby of mine, the waltz is a simple dance, but it has incredible depth. I can teach you the basics in an hour.

No, you can't. But that's not your fault..

 

I'm not pleased with Matt Heck's categorical comment about templates. The example just given, the circular/ring buffer, is an excellent example on how generics are much easier  and clearer in C++ than in C. Also, for some cases, it makes perfect sense to utilize some of STL. It's the same old story, again.. Use things blindly. Fail. Have insight. Succeed.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Keith how ate you doing interrupts in C++. Presumably ditching the ISR() mechanism the CRT provides? . The issue is that very thing you mention - trying to get a pointer to a function "inside" a class (so it kind of has to be static )

 

Clint

Yeah, thats one ugly part.

I basically poll the I/O

Luckily I/O is usually pretty slow

 

If you _need_ a callback, due to tight timing, you need a static member variable that points to the class instance.

Set the instance to yourself on construction

Then IRQ, which is a static function, then uses the static instance variable to call into the non static class.

Doable but ick.

 

It's also possible sometimes to make the whole class static, but thats a mess of a different color.

 

 

Keith Vasilakes

Firmware engineer

Minnesota

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

keith v wrote:
My latest project is 100% c++, all the interrupts [...] all C++.

 

clawson wrote:
The issue is that very thing you mention - trying to get a pointer to a function "inside" a class (so it kind of has to be static )

 

As far as I know and understand it has to be static. Can't see how hardware and "vectoring" can know which object instance to use for the this-pointer.

 

Also, as long as we're talking avr-gcc/avr-g++/avrlibc, I have assumed the ISR needs to have "C linkage" rather than "C++ linkage". I suppose this could be changed by one supplying new/altered startup code, though.

 

@keith v: If you have a technique outside of what me and Cliff just said, we'd  be genuinely interested in being taught it! ISRs in C++ (avr-g++) is one of the things many newcomers to the AVR and C++ combo ask about. (Just to be clear: Do not misunderstand this! I'm not picking a fight or some such! I'm genuinely interested if you know something I/we don't!)

 

keith v wrote:
C++ is not too hard, you're too weak.

LOL! Literally!

 

To play along with your SF wordplays: ALL THESE LANGUAGE FEATURES ARE YOURS, EXCEPT TEMPLATE META PROGRAMMING. ATTEMPT NO USAGE OF THAT.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess I kinda exaggerated, the interrupt handlers are in c++ but they are static, the actual ISR is a non member function so GCC knows what to do.

You guys do sound like you know whats going on C++ wise, and I know you know you c AVR stuff.  We definitely arent arguing.

 

I still like C++, and will continue to use it when I can. I mean the warts on C are way way bigger IMHO.

 

I dont know who Matt Heck is, but I do know Micheal Barr likes C++

Keith Vasilakes

Firmware engineer

Minnesota

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are a couple of things that are particularly off-putting to a C/asm programmer when a C++ programmer tries to wax poetic on its virtues...

 

  1. "It has this important feature." (describing some feature that your C compiler has had for decades, like "inline", or "const can replace #define", or "better type checking than pre-prototype C functions.")
  2. "<really expensive feature> is very powerful!" - like STL, or like using exceptions instead of explicit parameter verification.
  3. "You don't really need <important feature> because you can do <expensive alternative>", rather like:

I basically poll the I/O [instead of being able to handle interrupts properly]

 

Templates do not, on their own, cause problems.

 That's what I thought...  Do C++ programmers regularly say "templates" when what they mean is "The Standard Template Library" ?  The STL certainly seems to be a set of lovely functions generalized with dynamic allocation and exception handling to the point where you would have to do a lot of work to make it work well on a deeply embedded system.  But I don't see any reason why templates (or even TMP) in general can't be used to implement useful microcontroller-based things (though, come to think of it, "real C++ programmers" might Frown Mightily at such code.)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One thing I find off-putting about OOP on an AVR is the fundamental architecture.

 

An 'Object' contains both data (attributes) and code (procedures) all in one lump.  An object-oriented program is then constructed out of many of these lumps.

 

This is in complete contravention of the AVR's Harvard architecture, where the data lives over there (in the SRAM or EEPROM) and the code lives over here (in the flash).* 

 

It probably makes a lot more sense on a PC, where everything's in RAM.  Of course, that causes all sorts of fun stuff when your data starts to overwrite your code.  AVRs don't do that.**

 

S.

 

* Generally speaking.  I know you can put static data in the flash, and execute code from SRAM via a bootloader (through writing it into flash), et cetera, but the concept still holds.

** Unless you have a lot of SPM instructions lying around for writing self-modifying code, in which case may your Lord have mercy upon your soul.  Or a screwed-up bootloader.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:
One thing I find off-putting about OOP on an AVR is the fundamental architecture.

 

An 'Object' contains both data (attributes) and code (procedures) all in one lump.  An object-oriented program is then constructed out of many of these lumps.

 

This is in complete contravention of the AVR's Harvard architecture, where the data lives over there (in the SRAM or EEPROM) and the code lives over here (in the flash).*

Not relevant.

OOP does not require copying code at runtime.

The code associated with an object is the code associated with its classes.

Virtual tables do not contain code.

They contain pointers to code.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Could someone explain me better what is the problem of ISRs in C++? (probably it will not be possible, since I don't know almost anything of OOP)

Is it because you want to put them inside a class? Does that even make sense? I mean, "main" and all initialization that comes before, are an ISR (Reset).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think that would be better as a separate thread!

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:

One thing I find off-putting about OOP on an AVR is the fundamental architecture.

 

An 'Object' contains both data (attributes) and code (procedures) all in one lump.  An object-oriented program is then constructed out of many of these lumps.

 

This is in complete contravention of the AVR's Harvard architecture, where the data lives over there (in the SRAM or EEPROM) and the code lives over here (in the flash).*

 

On relevancy:

 

skeeve wrote:

Not relevant.

OOP does not require copying code at runtime.

The code associated with an object is the code associated with its classes.

Virtual tables do not contain code.

They contain pointers to code.

 

by line:

 

1) No, OOP does not require it.  But it is a feature of the language.

2) Um, yeah.  So?

3) & 4) Pointers are code.

 

There's a lot of good done with OOP.  Furthermore, the compilers cheerfully split it all up as they feel like, and I'm sure it does what it is supposed to do.  But I don't think much of it on an AVR.  My US$0.02

 

S.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
I suppose this could be changed by one supplying new/altered startup code, though.
Had the very same thought yesterday. For C++ instead of __vector_1, __vector_2 etc the weak linked jump destinations should be something like _Z8vector01v or whatever the mangled name for a void fn(void) happens to be. However they'd still be "classless" even if they had C++ linkage. But it just saves a little bit of extern "C" grief.
El Tangas wrote:
Is it because you want to put them inside a class? Does that even make sense?
The classic example (as shown by Arduino) is going to be something like a Serial/Uart class. You want to "connect" your RXC interrupt to a handler (probably a ring buffer stuffer) in the Uart/Serial class. As a typical AVR has from 1 to 8 (is it on Xmega?) UARTs you want to be able to write the class to cope with a "generic UART" then at instantiation you say "Uart Uart0(&UCSR0A, &UCSR0B, &UDR0 etc)". That instance will have the ring buffer for RXC on Uart0. Then you have instance "Uart Uart1(&UCSR1A, &UCSR1B, &UDR1...)" and so on. But somehow you have to map the fixed, C named UART0_RXC_vect (which is probably really __vector_17 or something) to the ring stuffer (oo, dreadful phrase!) in Uart0{} and UART1_RXC_vect (__vector_23 etc) to the ring stuffer in Uart1{} and so on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, ok I see the problem, thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

JohanEkdahl wrote:
I suppose this could be changed by one supplying new/altered startup code, though.
Had the very same thought yesterday. For C++ instead of __vector_1, __vector_2 etc the weak linked jump destinations should be something like _Z8vector01v or whatever the mangled name for a void fn(void) happens to be. However they'd still be "classless" even if they had C++ linkage. But it just saves a little bit of extern "C" grief.
El Tangas wrote:
Is it because you want to put them inside a class? Does that even make sense?
The classic example (as shown by Arduino) is going to be something like a Serial/Uart class. You want to "connect" your RXC interrupt to a handler (probably a ring buffer stuffer) in the Uart/Serial class. As a typical AVR has from 1 to 8 (is it on Xmega?) UARTs you want to be able to write the class to cope with a "generic UART" then at instantiation you say "Uart Uart0(&UCSR0A, &UCSR0B, &UDR0 etc)". That instance will have the ring buffer for RXC on Uart0. Then you have instance "Uart Uart1(&UCSR1A, &UCSR1B, &UDR1...)" and so on. But somehow you have to map the fixed, C named UART0_RXC_vect (which is probably really __vector_17 or something) to the ring stuffer (oo, dreadful phrase!) in Uart0{} and UART1_RXC_vect (__vector_23 etc) to the ring stuffer in Uart1{} and so on.

 

I don't see the C++ linkage as a problem, the IRQ is C but it can access a class instance just fine as long as there is a file global reference to it.

 

A better way to do that is to make 8 uart classes and then pass a ref to a serial class that then uses the uart. You'd also pass in you ring buffers and so on.

The serial class doesn't know about the uart hardware and the uarts are specific to the desired hardware allowing different uart setups per instance.

The uart class would also handle the ISRs

 

This also allows unit testing the serial class with a mock uart.

 

C and esp embedded programmers have a hard time with this because it looks like so much extra code. But it's not really. it's the same as in C just more organised.

Keith Vasilakes

Firmware engineer

Minnesota

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
30+ year old keyboards: from their original prototypes. (even if most of the labels are now worn off).

 

Never mind wearing the labels off - I seem to have worn a hole in the LH Shift key:

 

surprise

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:
On relevancy:

 

skeeve wrote:

Not relevant.

OOP does not require copying code at runtime.

The code associated with an object is the code associated with its classes.

Virtual tables do not contain code.

They contain pointers to code.

 

by line:

 

1) No, OOP does not require it.  But it is a feature of the language.

2) Um, yeah.  So?

3) & 4) Pointers are code.

1) Not of C++.

2) In C++, though admittedly not Python, the classes and their code are fixed at startup.

3 & 4) Pointers are not code.  In an AVR, the IJMP and ICALL pointers are not in program memory.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Jan, BRILLIANT link! Says it all really. . Oh and I'm intrigued he recommends Python as a first language. Couldn't agree more. Wish it had been around when I started!
just fyi from another thread: I love you again now. Python is my lifeblood.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

Witness the number of beginners here trying to start out on a USB project ...

 And I still consider TWI as "advanced"!

 

Jim

 

That's because TWI/I2C is evil! I have some locking issues that I can only fix with some elaborate reset code. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:

So here is a rather useless test program I wrote. But this certainly has potential even for MCU programming.

But you can do almost the same thing in C, though it's somewhat uglier (but also less mysterious?)

enum port_label {B, C, D};

static inline volatile uint8_t * Port(enum port_label t){
	switch (t) {
		case B:
			return & PORTB;
		case C:
			return & PORTC;
		case D:
		    return (volatile uint8_t *) & PORTD;
	}
}

int main (void) {
	*Port(B) = 0xFF;
	*Port(C) = 0xFF;
	*Port(D) = 0xFF;
}

 

(I actually had quite a bit of this sort of problem.  People would enthusiastically point out some object-oriented THING you could do in C++, and I would be "but I'm already doing that in ordinary C; why do I need a new language?"  Of course, the C implementation was a bit weird, and typically hid some ugliness inside C macros, so arguably C++ did have advantages.  At the moment, people seem to be all excited about "lambdas", and I'm thinking "pointers to functions; big deal.  Except now you don't have to explicitly write the function you're pointing to.  Which is good because...  because ...  ??  Because the "obfuscated c++ contests" can get even more mysterious entries?")

 

 

This exact reason is why I hate lambdas in Python, the language whose entire purpose is to be readable. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lambdas can make code clearer and easier to read. As always, if used "right".
.
Of-course, if you arent familiar with the syntax, or even the concept, they are obfuscated to you.
.
One way to think about lambdas are as anonymous functions written "in situ".

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do use lambdas in my TKinter code, but much more rarely than most do. I know the syntax and concept. I just don't like it. However, in other languages I like them better. In Pyhton they bug me (especially when they're fed to filter or map when a list comprehension/generator would have been SO MUCH more idiomatic). The exampl of having access to the locals i a good one for C++, but I don't even think it's true for Python. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I started writing a general piece on C++ lambdas for those not not familiar with the concept. It got so long that I realized that posting it here would be a serious derail of the thread so I posten in a new thread instead:

 

https://www.avrfreaks.net/forum/l...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:
One thing I find off-putting about OOP on an AVR is the fundamental architecture.   An 'Object' contains both data (attributes) and code (procedures) all in one lump.  An object-oriented program is then constructed out of many of these lumps.   This is in complete contravention of the AVR's Harvard architecture, where the data lives over there (in the SRAM or EEPROM) and the code lives over here (in the flash).*    It probably makes a lot more sense on a PC, where everything's in RAM.

IMO OO make a lot of sense on AVRs too.

 

I don't see OO as a way to reflect the low-level Harvard architecture idiosyncrasies at all. On the contrary, I see OO as a way to "abstract away" parts of that, and to combine hardware (as in e.g. IO modules), low-level software (as in reading/writing e.g. IO locations) and also adding functionality. All this to create an abstraction that makes sense on a higher level.

 

If I want buffered USART I/O with flow control I for an application then I can combine all that stuff into a class that has the interface something like:

 

 

class BufferedSerial {
public:
  boolean dataReady();
  char read();
  void write(char c);
  
private:
  ...
}

The part of the class that is private (or possibly protected) is all that goey stuff like looking accessing I/O registers, handling ring buffers etc. On the "application level" there is no need to see that stuff at all. The application level just want's to see what it really needs to see of that serial communications "module".

 

I can't understand why, at the application level, you'd need to "be aware" of e.g. that AVRs are Harvard.

 

The parallell to some stuff in the plain old avrlibc C runtime library is obvious. Specifically the stdio stuff. write a putc() and a getc(), set up the stdin and stdout file streams - and shuffle all that out of the way in a separate source file. Then, in main() use printf(). Everything re how and where your written data ends up is abstracted away from the "application level" and there is no reason to care at all that this executes on a Harvard architecture.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:

3 & 4) Pointers are not code.  In an AVR, the IJMP and ICALL pointers are not in program memory.

 

Semantics, I guess.  What a pointer points at can be had from anywhere, but the fact that it is a pointer and should be treated as such counts as 'code'.  IMHO.

 

JohanEkdahl wrote:

I don't see OO as a way to reflect the low-level Harvard architecture idiosyncrasies at all. On the contrary, I see OO as a way to "abstract away" parts of that, and to combine hardware (as in e.g. IO modules), low-level software (as in reading/writing e.g. IO locations) and also adding functionality. All this to create an abstraction that makes sense on a higher level.

 

This, of course, being the whole point of abstraction.  In a way, AVRs themselves are highly abstracted - We're not doing the math on how much current is running through each transistor when we ask for, say, an 'add' instruction.

 

But sometimes it does matter.  Abstraction is one thing, but sometimes strange things can go wrong due to a misunderstanding of what's happening at a lower level, and fundamental comprehension of that is at least important, if not essential.  For example, your C++ code might be totally flawless, but if you're regularly asking for 50mA from an I/O pin, it's not going to work, because we can't completely abstract away just how much current is running (or trying to run) through a transistor.

 

I'm not saying OOP on AVR doesn't work.  I imagine it works fine.  It just bugs me. 

 

It also strikes me as a recipe for inefficiency, although I've never seen speed comparisons of half-decent C++ vs. C code on AVRs.  Depends a great deal upon the compiler, I would guess.  But if a C++ compiler has to work a lot harder to make code of similar speed and size, then the abstraction is not well-aligned to the hardware.

 

And one could also say that's irrelevant, because hardware is so cheap and so fast these days why bother writing efficient code?

 

S.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think your I/O pin example works well. The problem would be the same with a C or assembler programmer not aware of the current limit.

If someone can't be bothered to read the datasheet and understand the hardware it's not the fault of the programming language they chose.  You could actually prevent this issue  in C with the preprocessor or templates in C++.

 

Using C++ isn't any more inefficient then using C. 

Now, using older AVR's does prevent you from being extremely efficient with C++, but it's a beautiful thing on Xmega's (The IO/memory map is laid out consistently).

Both C and C++ have a level of abstraction that can be difficult for the compiler programmers to deal with. In fact plenty of issues arise before even getting to the C/C++ level (gimple/bitcode).

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's not so much the older AVRs, it's the older AVR programmers.  indecision

I still have a tube of 90S1200s.  Perhaps I should keep them as antiques.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:
It also strikes me as a recipe for inefficiency, although I've never seen speed comparisons of half-decent C++ vs. C code on AVRs. 

Oh, come on! That's just FUD.

 

Give examples.

 

If this is about using things when not needed, or using things in ignorance of their costs or other drawbacks, then I could argue about C that it is a recipe for inefficiency (well, even disaster) because someone might use dynamic memory allocation on a RAM-challenged AVR. If misuse of the language by ignorant users is a valid argument then not even assembler goes free..

 

So, can you be specific about what inefficiencies you expect C++ to force upon you? Facts, not hunches.

 

Sorry for the tone, but insinuations that C++ is inefficient surfaces ever so often. Here and elsewhere. And it's always like 99% ignorance.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An 'Object' contains both data (attributes) and code (procedures) all in one lump.  An object-oriented program is then constructed out of many of these lumps.

 But ... those "lumps" are just compile-time abstractions.  Even on a desktop von Neuman machine, your code is likely to end up in nice execute/readonly pages, and your data not remotely nearby (probably dynamically allocated, in fact.)  You might as well claim a C can't be supported on a Harvard architecture, because you can't distinguish "pointers to code" from "pointers to data."  (not that that isn't a problem.  But it's not nearly as much of a problem as you might think at first glance.)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:

Scroungre wrote:
It also strikes me as a recipe for inefficiency, although I've never seen speed comparisons of half-decent C++ vs. C code on AVRs. 

Oh, come on! That's just FUD.

 

Give examples.

 

I don't have any examples. 

I believe I said so.  See quotation above.

 

C++ could be slower.  C++ could be faster.  It's rare, though, that I see C++ advertised as high-performance.

 

And the whole point of the thread was "What makes C++ so "Hard"?"

This is why I think it's "hard" from my perspective.  This is my opinion.

 

And dynamic RAM allocation on a part that doesn't have any RAM will get you nowhere (some Tiny chips were like that.  I guess you could call the register file RAM if you wanted to).  I would hope that during compiling a program that tried to allocate more RAM than the chip had would cause errors, but I'm not sure.  If the compiler didn't error out the program certainly would.

 

I don't know enough C++ to write fair comparison tests.  I'm not going to compare C++ with hand-drawn assembler, because the latter is known to be a bit faster than bare C, and using the latter again as a comparison with C++ wouldn't be fair.  If anyone else would like to, that could be the test we need.

 

S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And obviously both C and C++ can be supported on a Harvard Architecture, because they both are.  Whether they are supported efficiently or not is an entirely different question.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

westfw wrote:
your code is likely to end up in nice execute/readonly pages, and your data not remotely nearby (probably dynamically allocated, in fact.)
+20

 

That's exactly what happens. Try debugging C++ in the Asm view on a PC (I do - old habits die hard!) and you will see exactly where things are located. In a class the "members" are quite distant from the methods that act upon them. So the memory space split in AVR is really no different.

 

As for "efficiency". I build small C and C++ examples to help in threads here all the time and on the whole the "core" of most functionality turns out almost identical whether C or C++ so this often proffered myth of C++ being "inefficient"/"bloaty" is just that, a myth. The one exception to this are the virtual table pointers which are known at compile time and thus could be flash located and accessed with LPM but in reality are RAM based - so they "eat" a bit of precious RAM that was not really required. But that's about the only inefficiency in C++ and, if only the GNU C++ dev team would allow such tings, the operation of compiler could be made more efficient for Harvard architecture processors.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Speaking of lambdas (thank you for the separate thread!), did C++ get any similar in-place creation of static const arrays and structures?  It's one of the things I've seen newbies try to do, and I've occasionally wanted something similar myself.  It seems like it would fall somewhere between quoted strings and lambdas in compile-time complexity:

  

typedef struct { volatile uint8_t & Port; uint8_t val } config_t;
  :
  write_sfrs({{config_t[]}}{
      { UCRSR0A, INIT_SRA },
      { UCRSR0B, INIT_SRB },
      { UCRSR0C, INIT_SRC }
  });

  (where my made-up syntax "{{type[]}}{stuff}" is supposed to mean "build a static const array of values of that type, containing "stuff")

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I accept clawson's verdict on this.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:
It's rare, though, that I see C++ advertised as high-performance.

That might be so, but is at least in part because you aren't looking. C++ folks themselves state repeatedly that one of the primary design goals is for C++ to be efficient. Very efficient. Right from the start.

 

You'd think that by now, 30+ years later, someone would have revealed the scam.

 

So, how often do you see C++ advertised as low-performance. And if so, is it backed up by anything?

 

Now, what does your "recipe for inefficiency" really amount to? Nothing, so far. No facts on the table. Not one little hint as to when this should be the case. Just a hunch.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Fri. Jul 14, 2017 - 10:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:
And obviously both C and C++ can be supported on a Harvard Architecture, because they both are.  Whether they are supported efficiently or not is an entirely different question. 

More FUD.

 

Come on, Scrounge. Put some evidence on the table!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please see posts #107 and #109.  Thank you.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How do we define 'efficient'? We seem to be happy with our automobiles being only 30% efficient and javascript on our browsers is considered adequate when it is really inefficient, so it comes down to what we are prepared to accept.

Last Edited: Fri. Jul 14, 2017 - 11:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is a good question, and like most good questions the answer is "it depends".

 

Spending a million bucks on software development to save one buck in hardware cost is a false economy - Unless you're shipping a million-plus units.

Burning away most of the flash to save a few cycles might be efficient - Or it might not (See:  Lookup tables vs. trig calculations).

 

As is typical of all engineering, it's a tradeoff.  Many tradeoffs, and judging which is the correct one is what engineers are supposed to do.

 

From my standpoint, I believe in using the least silicon to do the job, and although my time is valuable, I'd rather spend more time to use less silicon.  Others will, perfectly reasonably, disagree.

 

I am also distinctly unhappy with javascript on my web browsers and go to some efforts to limit it.

 

S.

 

"Engineering is the art of doing for a shilling what anyone can do for a pound".  Attributed to Nevil Shute Norway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre, you've never seen speed comparisons between C and C++ because you've never looked, there are tons of them.

 

General C/C++ ranting...

C++ speed is basically the same as C if written well.

C++ IS the language of choice in almost all applications requiring speed. It's a better C.

There ARE ways to make C++ slower, but thats because you write the code to be slow.

 

In 30 years of writing control software in C++ I've had to worry about speed like twice. Both doing heavy image analysis. Both situation were not solved by using assembler or dropping down to C, but by profiling the code and fixing the slow parts.

 

One of my favorite software conference classes was one given by the compiler writers from Borland, Microsoft and a few other big name compilers on how to optimize your code.

It started with them asking the audience about their favorite ways to write faster code. They wrote these down on the projector then ripped then to shreds showing why it was wrong.

Some audience members even trotted out the assembly language proof that these were faster and the writers, in every case, proved them wrong.

 

It was hilarious and basically turned into a rant about writing clean, standard obvious code so the optimizer can do it's analysis and create better decisions about what changes to make.

This does not of course mean you can do stupid things like putting code in loops that shouldn't be there.

 

So if you think you are smarter than the compiler writers, then go ahead, optimize away.

The language you use is a very small part of the speed issue.

Keith Vasilakes

Firmware engineer

Minnesota

Last Edited: Fri. Jul 14, 2017 - 03:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

keith v wrote:

So if you think you are smarter than the compiler writers, then go ahead, optimize away.

 

As a matter of fact, yes, I do.  I write native assembler.  And lo, it's faster.

I'm not smarter than the compiler writers, it's just that my code is faster, uses less space, and takes ten times longer to write.

 

Scroungre wrote:

Please see posts #107 and #109.  Thank you.  S.

 

Does anyone here actually read anything I write once they're all offended?

S.

 

 

PS - I write control software that does depend upon speed.  And I don't write it in C++.  Thank you.

Edited to add PS

 

Last Edited: Fri. Jul 14, 2017 - 03:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's not clear enough I guess, but I was only referencing your comment that you haven't seen any speed comparisions between the languages.

The rest of the post is not targeted at you.

 

Unless youve written your application in all 3 languages and are proficient in all 3 and then profiled your code, your statement that your assembler is faster is pure fantasy.

I have written assembler and C versions of the same app and I can confirm the asm version took 10 times longer to write.

Keith Vasilakes

Firmware engineer

Minnesota

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Indeed, I had not.  But clawson had.  I deferred to his superior experience.  Did you miss that bit?

 

I believe it is a matter of fact that hand-tuned assembler is faster than compiled assembler.  Provided both know what they are doing.  I like to think that I do.  I have no idea what the compiler authors think.

 

In many a post before I pointed out that I don't know enough C++ to write a reasonable comparison.  So I won't.  If you would like to, you're more than welcome.

 

Otherwise, I concur.

 

S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:
I believe it is a matter of fact that hand-tuned assembler is faster than compiled assembler.
OK, try to improve this...

C:\SysGCC\avr\bin>type avr.c
#include <avr/io.h>

int main(void) {
        while (1) {
                PORTB |= (1 << 5);
        }
}

C:\SysGCC\avr\bin>avr-gcc -mmcu=atmega16 -Os -g avr.c -o avr.elf

C:\SysGCC\avr\bin>avr-objdump -S avr.elf | tail -n 15

0000006c <main>:
#include <avr/io.h>

int main(void) {
        while (1) {
                PORTB |= (1 << 5);
  6c:   c5 9a           sbi     0x18, 5 ; 24
  6e:   fe cf           rjmp    .-4             ; 0x6c <main>

C / C++ compilers don't ALWAYS make a bad job of picking Asm opcodes ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here you go:

 

Unfortunately the 'code' bit on the fora doesn't work with my web browser, and so I'm going to have to just cook it up:

 

C:\whatever\type avr.asm

 

LABEL:

sbi PORTB, 5

rjmp LABEL

 

And here everyone tells me that writing assembler code is verbose.  Sheesh.

 

smiley   S.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One way to beat the compiler is to know something it does not.

clawson wrote:

Scroungre wrote:
I believe it is a matter of fact that hand-tuned assembler is faster than compiled assembler.
OK, try to improve this...

C:\SysGCC\avr\bin>type avr.c
#include <avr/io.h>

int main(void) {
        while (1) {
                PORTB |= (1 << 5);
        }
}

C:\SysGCC\avr\bin>avr-gcc -mmcu=atmega16 -Os -g avr.c -o avr.elf

C:\SysGCC\avr\bin>avr-objdump -S avr.elf | tail -n 15

0000006c <main>:
#include <avr/io.h>

int main(void) {
        while (1) {
                PORTB |= (1 << 5);
  6c:   c5 9a           sbi     0x18, 5 ; 24
  6e:   fe cf           rjmp    .-4             ; 0x6c <main>

C / C++ compilers don't ALWAYS make a bad job of picking Asm opcodes ;-)

To make it faster, use -nostarfiles and whatever else it takes to put the sbi at 0.

After that, nothing really matters, since PORTB will never change.

If one is nevertheless interested in the loop rate,

the following are both faster:

0:  sbi PORTB, 5
    sbi PORTB, 5
    rjmp 0b

0:  ldi r16, 1<<5
2:  out PORTB, r16
    rjmp 2b

Dealing with the possibility of an always on watchdog is left as an exercise for the reader.

Edit: Nevermind. The default is reset mode.

Moderation in all things. -- ancient proverb

Last Edited: Sat. Jul 15, 2017 - 12:25 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lads I am talking about the two opcodes:

  6c:   c5 9a           sbi     0x18, 5 ; 24
  6e:   fe cf           rjmp    .-4             ; 0x6c <main>

How can what this does be made "shorter" in hand crafted asm? The assertion was "matter of fact ... assembler is faster than compiled assembler" (I take that to really mean "compiler generated assembler"?)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, I'm ending this here.

 

clawson wrote:

C / C++ compilers don't ALWAYS make a bad job of picking Asm opcodes ;-)

 

Not always.  Good assembler coders don't ever.  So there.  Shall we be done with compiler fights now?

 

S.

 

Okay, if you really want to fight, show me C code that divides by 256 (and truncates) and I'll show you assembler that is faster.  S.

 

Last Edited: Fri. Jul 14, 2017 - 05:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scroungre wrote:

Okay, if you really want to fight, show me C code that divides by 256 (and truncates) and I'll show you assembler that is faster.  S.

 

I'll bite. How do you make this faster?

c@foo:~$ cat divide-by-256.c
unsigned int div256(unsigned int x)
{
    return x / 256;
}
c@foo:~$ avr-gcc -O2 -S divide-by-256.c
c@foo:~$ cat divide-by-256.s
        .file   "divide-by-256.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
        .text
.global div256
        .type   div256, @function
div256:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
        mov r24,r25
        ldi r25,0
        ret
        .size   div256, .-div256
        .ident  "GCC: (GNU) 4.9.2"

Seems that it's as small and fast as it can get (and it would be smaller/faster if it were inline and the compiler knew where the value were going, such as into an 8-bit variable).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The div256 routine is perfectly legal C, although that's what I'd call inline assembler.  The benefit of using pure assembler is that you don't have to move r25 into r24 and you don't have to clear r25 if you can just ignore it.  Save two cycles there.  And nothing about where the C function puts the return value.

 

S.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just so that I understand you correctly.. Are you saying you call

unsigned int div256(unsigned int x)
{
    return x / 256;
}

"inline assembler"?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No.  I call:

 

christop wrote:

 

c@foo:~$ cat divide-by-256.c
div256:
        mov r24,r25
        ldi r25,0
        ret

 


 

inline assembler.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

(And I'd use 'clr r25' not because it makes any difference to execution speed but because it's shorter to type and makes is clearer (heh) what is intended to do with it.  Not that it matters - In assembler code the output can be any register, or register pair)  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Scroungre wrote:
I believe it is a matter of fact that hand-tuned assembler is faster than compiled assembler.
OK, try to improve this...

C:\SysGCC\avr\bin>type avr.c
#include <avr/io.h>

int main(void) {
        while (1) {
                PORTB |= (1 << 5);
        }
}

C:\SysGCC\avr\bin>avr-gcc -mmcu=atmega16 -Os -g avr.c -o avr.elf

C:\SysGCC\avr\bin>avr-objdump -S avr.elf | tail -n 15

0000006c <main>:
#include <avr/io.h>

int main(void) {
        while (1) {
                PORTB |= (1 << 5);
  6c:   c5 9a           sbi     0x18, 5 ; 24
  6e:   fe cf           rjmp    .-4             ; 0x6c <main>

C / C++ compilers don't ALWAYS make a bad job of picking Asm opcodes ;-)

 

Cmon, everyone knows that hand optimized ASM cannot be beaten, at most it can be matched, no need to start a war...

That one is easy, just unroll the loop.

 

loop:
    sbi     0x18, 5   
    sbi     0x18, 5   
    sbi     0x18, 5
    rjmp    loop

Now we have one I/O per 2.7 cycles, while the C code needs 4 cycles. Thus, 50% improvement in speed, at the cost of flash.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You might think so, Mr. Tangas, but it seems that some disagree with what both you and I find obvious.  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No.  I call:

[...]

inline assembler.  S.

 

OK. But that is the code generated by the compiler from the function in C written by christoph. 

 

Notice he is typing out the .lss file, which is a listing of what the compiler produced:

c@foo:~$ cat divide-by-256.s
   .
   .
   .

 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Fri. Jul 14, 2017 - 09:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, just to be clear...  If I have a C++ object like:

class SERCOM
{
	public:
		SERCOM(Sercom* s) ;

		/* ========== UART ========== */
		void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0) ;
		void initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits) ;
		void initPads(SercomUartTXPad txPad, SercomRXPad rxPad) ;

		void resetUART( void ) ;
	
		/* ========== SPI ========== */
		void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder) ;
		void initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate) ;

		void resetSPI( void ) ;
		void enableSPI( void ) ;
		void disableSPI( void ) ;

		/* ========== TWI ========== */
		void initSlaveWIRE(uint8_t address) ;
		void initMasterWIRE(uint32_t baudrate) ;

		void resetWIRE( void ) ;
		void enableWIRE( void ) ;
 // etc

 

All those per-class functions ("Methods") do NOT take up space in any SERCOM object I happen to declare or allocate.   Unless the methods are virtual, all the resolution of of "mysercom.resetWIRE();" and similar end up being just compile and link-time name-munging, and will end up in the object code as simple call instructions to absolute addresses.

(Is that right?)

 

If I DO declare the methods as virtual, then each object will end up with a pointer to a functions, and each call is equivalent to "(*struct->fptr)(args);", but with much simpler source-code syntax...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
All those per-class functions ("Methods") do NOT take up space in any SERCOM object I happen to declare or allocate. 

If that is a question: No, they do not take up space.

 

I'll try this again (typed in explanations like this 10 times now I guess...), with a different angle:

 

There is nothing magic about objects. There  is nothing magic about member function calls. The objects holds the data from the class definition. It's like your good old C struct.

 

The call to a member function:

myObject.foo(int someParameter);

will be implemented as a call with parameters:

  1. The hidden this-pointer.
  2. Thee explicitly stated parameters (in this case one int).

 

It corresponds precisely to the C case

foo(MyStruct struct, int someParameter);

That's "all" there is to it.

 


 

For virtual funcdtions it get a little more hairy. Each object has a pointer to it's vtable. The vtable as such exists in one instance per class (not object!) with virtual methods. It is a table of pointers to the functions themselves.

 

Thus, calling a virtual function for an object, like so

class MyClass {

   virtual void bar(int i);
}

MyClass myObject;

int main() {
    myObject.bar(42);
}

means

  1. Follow the vtable pointer in the object.
  2. Pick the applicable function pointer from the vtable. NOTA BENE: This is a simple indexing operation! There is no "search" at run-time. The compiler has, at compile time, determined the offset into the vtable for the function in question.
  3. Push parameters (in this case the this-pointer and the 42.
  4. Call.

Points 3 and 4 the same as for any ordinary non-virtual call. So the extra cost is "two indirections".

 


 

If in doubt about what happens you can inspect the generated source and/or step through the disassembly.

 

Again, there's no magic here. And it's not very complicated. On a few occasions, when speaking to people about how C++ actually works and how it is not less efficient than C, the coin suddenly drops and they are surprised about the non-complexity of the "mechanisms behind the scenes". For anyone genuinely interested, I urge you to do the investigation into generated code. Things will be much clearer, e.g. re virtual functions.

 


 

And the "caveat emptor", as always when talking C++ on AVRs, efficiency, virtual functions and the avr-g++ compiler: Unfortunately, the compiler places the vtable in RAM. It could have been in flash ROM since it is immutable at run-time. The cost of a vtable is the size of a function pointer times the number of virtual functions the class has.

 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Jul 22, 2017 - 09:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's another view on it:

 

The first C++ compiler was "Cfront". This is what Bjarne et al used in the beginning. It compiles the first rudimentary C++ into C. Apart from making things independent of environment (OS, processor..) it made for inspecting what the compiler did easier. The generated C code was then compiled into a target-specific executable.

 

Simplifying/sketching things, here's what Cfront did to a simple class:

 

class C {
    int i;

    void f(j) {
        i = j;
    };
}

   .
   .
   .
   C object1;
   C object2;

   object1.f(42);
   object.f(7);

 

Compiled into C:

 

typedef struct {
    int i;

} C;

void f(C * this, int j) {
    this->i = j;
};

   .
   .
   .
   C object1;
   C object2;

   f(&object1, 42);
   f(&object2, 7);

Again: There's no magic. Just a bit of "behind the scenes".

 

Observe:

  • There is one implementation of f.
  • There is no extra cost of declaring a class, or rather defining an object, as compared to the C variant.

 

In reality it is a wee bit more convoluted, mainly because of overloading. There is the possibility to have several functions f() with different signatures, and thus "name mangling" comes into play.

 


 

It's a bit harder to make a simple readable example for virtual functions. I believe there will be a bit of typecasting going on because of the vtable holding function pointers to functions with different signatures. To be really sketchy:

class Super {
    int i;

    virtual void f(int j) {
        i = j + 1;
    }
}

class Sub : Super {
    virtual void f(int j) {
        i = j * 2;
    }
}

   .
   .
   .

   Super object1;
   Sub object2;
   Sub object3;

   object1.f(42);               // object1.i becomes 43

   object2.f(7);                // object2.i becomes 84

   object3.f(100);              // object3.i becomes 200

   Super * object4 = &object2;  // Up-cast is safe!
   object4->f(9);               // NOTA BENE: object2.i becomes 18!

The C++ code is really sketchy..

//--- The Super class ---

// Typedef for the vtable
typedef struct {
    void (*f) (int);
} SuperVtable;

// The vtable instance
SuperVtable superVtable = {
    .f = &Super_f;
}

The struct type for the Super class
typedef struct {
    int i;
    SuperVtable * vtable = superVtable;
} Super;

// The member function
void Super_f(Super * this, int j) {
    this->i = j + 1;
}

//--- The Sub class ---

// Typedef for the vtable
typedef struct {
    void (*f) (int);
} SubVtable;

// The vtable instance
SubVtable subVtable = {
    .f = &Sub_f;
}

// The struct type for the Sub class
typedef struct {
    SubVtable * vtable = subVtable;
} Sub;

// The member function
void Sub_f(int j) {
    i = j * 2;
}

   .
   .
   .

   Super object1;
   Sub object2;
   Sub object3;

   // object1.f(42);
   object1.vtable->f(42);               // object1.i becomes 43

   //object2.f(7);
   object2.vtable->f(7);                // object2.i becomes 14

   // object3.f(100);
   object3.vtable->f(100);              // object3.i becomes 200

   //Super * object4 = &object2;        // Up-cast is safe!
   // object4->f(9);
   object4->vtable->f(9);               // NOTA BENE: object2.i becomes 18!
                                        // While object3 is a pointer to a Super
                                        // it actually points to a Sub so the vtable
                                        // for a Sub will be used. THAT is polymorphism!

There's probably all sorts of formal shortcomings in the above C code. Forward declarations missing for one thing.

 

Please try to oversee that, and look at what is happening. 

 

hope I got everything correct as far as possible in the code above. If you see anything that seems to be a typo, please comment. 

 


 

If you really want to play around, it seems you can actually download Cfront from here: http://www.softwarepreservation.... . To be honest, I haven't ever done that but I've been tempted - just to see if I can get it going.

 


 

EDIT: I actually took a shot at pushing the above C code (second example, for virtual functions) through the compiler and it's a mess. See  below for something that I actually got to compile clean. (It does not add much to the illustration though - mostly extra fluff/confusion to keep the C compiler happy. See it only as a demonstration on what memory allovcation goes on, and how a virtual function call is implemented).

//--- The Super class ---

// Need a forward declaration of the vtable struct
typedef struct SuperVtable SuperVtable;

// The struct type for the Super class
typedef struct Super{
    int i;
    struct SuperVtable * vtable;
} Super;

typedef struct SuperVtable{
    void (*f) (struct Super * this, int j);
} SuperVtable;

// The member function
void Super_f(struct Super * this, int j) {
    this->i = j + 1;
}

// The vtable instance
SuperVtable superVtable = {
    .f = Super_f
};


#if 1
//--- The Sub class ---

// Need a forward declaration of the vtable struct
typedef struct SubVtable SubVtable;

// The struct type for the Sub class
typedef struct Sub {
    int i;
    SubVtable * vtable;
} Sub;

// Typedef for the vtable
typedef struct SubVtable{
    void (*f) (struct Sub * this, int j);
} SubVtable;

// The member function
void Sub_f(struct Sub * this, int j) {
    this->i = j * 2;
}
// The vtable instance
SubVtable subVtable = {
    .f = Sub_f
};



#endif

int main(char * argv[], int argc) {

   Super object1;
   object1.vtable = &superVtable;

#if 1
   Sub object2;
   object2.vtable = &subVtable;
   Sub object3;
   object3.vtable = &subVtable;
#endif
   
   // object1.f(42);
   superVtable.f(&object1, 42);         // object1.i becomes 43
                                        // I think, but not sure that...
                                        // since we have an object
                                        // variable rather than a pointer-to-object
                                        // the compiler can refer directly to the
                                        // vtable (without going through the
                                        // objects vtable-pointer). It KNOWS
                                        // object1 is precisely a Super.

   //object2.f(7);
   subVtable.f(&object2, 7);            // object2.i becomes 14

   // object3.f(100);
   object3.vtable->f(&object3, 100);    // object3.i becomes 200

   //Super * object4 = &object2;        // Up-cast is safe in C++!
                                        // In C Super and Sub are incompatible
                                        // types so it is not possible to
                                        // do
                                        //    Super * object4 = &object2;
                                        // Since I know that the layouts are
                                        // identical I will do an ugly cheat
                                        // and...
   Super * object4 = (Super *)(&object2);
   // object4->f(9);
   object4->vtable->f(object4, 9);      // NOTA BENE: object2.i becomes 18!
                                        // While object3 is a pointer to a Super
                                        // it actually points to a Sub so the vtable
                                        // for a Sub will be used. THAT is polymorphism!
}

Now I'm really getting tempted to try out Cfront! (But I have other things prioritized (apart from eternally defending C++ from FUD). Some of you might have seen my lengthy thread on getting a decent AVR development environment running on GNU/Linux (ICE debugging...). So Cfront will be pushed back.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Jul 22, 2017 - 06:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A picture says...

 

 

NOTA BENE: Re hte placement of the vtables, this is specific to the avr-g++ compiler. Other compilers might behave better in this respect and place them in flash ROM.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Jul 22, 2017 - 12:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the IT industry it's Java, C# .NET and maybe PHP. Python and Ruby are new kids on the block. VB was the runt of the litter.

 

I understand the software industry loves C++. They tend to have advanced degrees though. Maybe that's why they don't get injured as much while handling a dangerous tool like C++.

 

In the IT industry it has a reputation for terrible applications the just keep breaking and extremely difficult bugs such as memory leaks, pointer issues, strange combinations of keywords that no one can figure out.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Darrough wrote:
In the IT industry it's Java, C# .NET and maybe PHP. Python and Ruby are new kids on the block. VB was the runt of the litter.

 

I understand the software industry loves C++. They tend to have advanced degrees though. Maybe that's why they don't get injured as much while handling a dangerous tool like C++.

 

In the IT industry it has a reputation for terrible applications the just keep breaking and extremely difficult bugs such as memory leaks, pointer issues, strange combinations of keywords that no one can figure out.

Anything can be done badly.

It seems that several someones have been writing code they do not understand.

That is one way to do it.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@Darrough:

 

You're not making much sense now, are you?

 

  • Earlier you have argued against C++ (and pro C it seemed) because of alleged inefficiency in C++. This claim has been rejected thoroughly.
  • Now you argue against C++ because of it being a "dangerous tool" and allows for "bugs such as memory leaks, pointer issues". Well, in that respect C is worse than C++, which e.g. does have a higher degree of type safety, and allows for somewhat safer pointer handling (if you know how to do it).

 

So on one hand you seem to argue for C over C++. On the other hand some arguments you pose re C++ holds in an even greater extent for C.

 


 

skeeve wrote:
In the IT industry it has a reputation for terrible applications

It is true that C++ is less "forgiving" than any of the high-level languages you name (Java, C#, Python, Ruby...) But since we are talking embedded systems here those language does not apply much for anything but the largest embedded systems. I.e. "hosted" systems (huge memory, has operating system etc) like a Busybox system, Android etc..

 

For systems "on the bare metal" those languages are not an alternative.

 


 

Darrough wrote:
strange combinations of keywords that no one can figure out

"No one" is a stupid and false generalization. It is true that one needs to learn the language to be able to use it. Suggest you stay away from C++.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Jul 22, 2017 - 06:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Earlier you have argued against C++ (and pro C it seemed) because of alleged inefficiency in C++. This claim has been rejected thoroughly.

 

I did not argue against anything, merely asked if it wasn't true that object oriented programming and design patterns are not a good fit for small systems. You pointed out that some AVR projects can have 1000's of lines of code. You also made a point about reuse. I would not consider that "rejected thoroughly".

 

JohanEkdahl wrote:
Now you argue against C++ because of it being a "dangerous tool" and allows for "bugs such as memory leaks, pointer issues". Well, in that respect C is worse than C++, which e.g. does have a higher degree of type safety, and allows for somewhat safer pointer handling (if you know how to do it).

 

Once again, I did not argue against anything, I merely stated that it has a bad reputation in the IT industry. That is a fact which I can substantiate with 14 years of experience in IT.

 

From a technical point of view one cannot criticize C++, but there is more to the evaluation of a compiler than the technical facts. It has to be considered how well has it served programmers. And the largest body of programmers, the IT industry, pretty much won't have anything to do with it.

 

JohanEkdahl wrote:
"No one" is a stupid and false generalization. It is true that one needs to learn the language to be able to use it. Suggest you stay away from C++.

 

And I suggest that you take the blindfold off, because the languages numerous modifiers and specifiers are counter productive in a real programming environment.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The objects holds the data from the class definition.

 I do "get" this; I'm worried that C++ instruction contains so much "In an OOL, data and methods are combined into one object that groups them together" rhetoric that this becomes a worry of experienced embedded programmers.

 

 

the language's numerous modifiers and specifiers are counter productive in a real programming environment.

This is like saying "C's case sensitivity of symbol names is counter productive to understandable code, because you might use MyVariable and myvariable and my_variable and myVariable all in the same program."  If there are modifiers and specifiers that you feel are counter-productive in your environment, by all means feel free to NOT USE THEM.  And establish a coding standard that says that they shouldn't be used...  It's very rare for ANY computer language to have all of its features utilized...

 

The last place I worked had occasional discussions on whether we should start using or at least allowing C++ (already having a very OOP-in-C infrastructure.)  And our general conclusion was that it would make it too easy to "accidentally" do something with a significant performance impact, NOT that it had inherently poor performance.

 

As an interesting thought experiment, I doubt that there are many examples of "real" C++ programs" on the web that 10 randomly-chosen "experienced C++ programmers" will agree that "this is a good example of how a C++ program should be written."

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you need a few years experience of both C and C++ before you can pass judgement on their relative merits. I have almost 20 years C and now 5+ for C++ and have now completely changed my initial opinion of C++. I'm now hard pushed to think of any way in which C is "better" than C++ and all this talk of slow/bloaty clearly comes from the ill informed who obviously aren't regularly using the language. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I'm now hard pushed to think of any way in which C is "better" than C++ and all this talk of slow/bloaty clearly comes from the ill informed who obviously aren't regularly using the language. 


C has one feature that I like and use all the time that C++ doesn't have: designated initializers. I use them for creating all sorts of mapping arrays, such as a map of error codes to error message strings, and I also use them to create functions that can take named arguments. I'm posting this from my phone so I can't easily write code to show what I mean by that. I'll write an example later when I'm at a computer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chridtoph!

 

Not sure if this is helping you, but have you looked at C++11 constexpr?

 

http://en.cppreference.com/w/cpp...

http://www.sourcetricks.com/2013...

https://stackoverflow.com/questi...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Darrough wrote:
And I suggest that you take the blindfold off, because the languages numerous modifiers and specifiers are counter productive in a real programming environment.

 

In retrospect I think this comment was overstated. My apologies.

 

From a technical point of view there is nothing wrong with C or C++.

 

I just fanatical to give it to the programming community, watch it sink, and then declare that its not the compilers fault, the problem is with the programming community.

 

I am not criticizing the language. I am criticizing the fanatics that try to push C or C++ as the best all around language.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely the initializer list on the class c'tor serves the same purpose (initialization of selected members) it's simply a different syntax. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I'm at a computer now with some examples to show what I mean.

 

Here's my first example of designated initializers, for mapping arrays:

const char *error_messages[] = {
	[E_NONE] = "No error",
	[E_NO_SUCH_USER] = "No such user",
	[E_INVALID_INPUT] = "Invalid input",
	[E_TOO_MANY_TACOS] = "Too many tacos",
};

I also use that technique for mapping device-specific status codes to my own status code enumeration:

const enum Status device_status_map[] = {
	[0] = STATUS_EMPTY,
	[1] = STATUS_LOW,
	[2] = STATUS_OK,
	[3] = STATUS_ALMOST_FULL,
	[4] = STATUS_FULL,
};

I know there's maps and other such things in C++, but they are more heavyweight than using a small integer as an index into an array.

 

The other use, named arguments, borders on preprocessor abuse:

// our named argument structure
struct drawCircle {
	int x, y, radius;
};

// the real function
void drawCircleS(struct drawCircle dc) {
	// draw a circle using dc.x, dc.y, dc.radius
}

// our "function" that takes named arguments and has a default value for each argument.
#define drawCircle(...) drawCircleS((struct drawCircle){ .x = 1, .y = 2, .radius = 3, __VA_ARGS })

// then call it like this:
drawCircle(.x = 7, .y = 8, .radius = 9);

// or like this:
drawCircle(.radius = 9, .x = 7, .y = 8);

// or even like this to use the default radius:
drawCircle(.x = 7, .y = 8);

I know there's other ways to do something similar in C++, such as chained setters (e.g., parameters.setX(7).setY(8).setRadius(9).drawCircle()), but I like that it's compact and resembles other languages with named arguments, like Ada or Common Lisp.

 

JohanEkdahl: I'm not a C++ expert, so I'm not sure how constexpr can be used to implement something like the above. Do you have any examples?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I see what you're after. Not even close to my hunch.. 

 

So constexpr is nothing that can do that for you. It's a mechanism to guarantee that a something is a build time expression (or emit an error if that's not possible).

 

I'm thinking your second case above might be implemented by setters, or maybe some named parameter idiom, hidden behind a VA_ARGS macro just as you do. Not enough knowledge about variadic macros, so would need to read up on stuff and then experiment.

 

I'm thinking even harder about your first example but can't see any such "neat" C++ solution.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am a little distressed that C and C++ seem to be diverging; I *liked* that C++ was supposed to be a superset of C.

Now we have Christop's designated initializers and the whole AVR "named address spaces" that aren't in C++   :-(

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes. Some diverging is inevitable, methinks. The C++ folks had "almost a superset" as a design goal (never "a complete superset" as far as I know). But there was other design goals also.

 

If C "moves" (gets new features) then the C++ folks might well be in a situation where not following suite might break one design goal but following suite breaks another.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From a brief search it looks like Microsoft and clang have added extensions to C++ to allow designated initializer's and people are trying to get it added to the next C++ standard.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

atomicdog wrote:
people are trying to get it added to the next C++ standard

Yes. And during a search I saw traces of attempts to have it added to C++14 C++17. That didn't happen.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Mon. Jul 24, 2017 - 10:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C++17 will be along shortly cheeky

 

(that was one of my points above - this language is still "growing" so every 3 years there's going to be new stuff to learn).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh, sorry - I said C++14 above but meant C++17. No, designated initializers didn't make it into C++17 as far as I know.

 

The workgroup(s) are done, there is a last draft for the standard released: http://www.open-std.org/jtc1/sc2...

 

I would be very surprised to see anything but minor corrections/adjustments.

 

Next tentative standard is C++20, IIRC.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Mon. Jul 24, 2017 - 10:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Next tentative standard is C++20, IIRC.
Bound to be - they have now entered a pattern of every 3 years so 11, 14, 17, 20, 23, 26, 29, ....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
I *liked* that C++ was supposed to be a superset of C

I'm not sure that was ever actually true?

 

They certainly shared a (large) common subset - but  I didn't think C++ was ever a strict superset of C ... ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
westfw wrote:
I *liked* that C++ was supposed to be a superset of C

I'm not sure that was ever actually true?

 

They certainly shared a (large) common subset - but  I didn't think C++ was ever a strict superset of C ... ?

'Twas supposed to be close,

hence the name.

Never was exactly.

There were always programs valid as C and as C++, but semantically different.

Two issues come to mind:

C++'s comments allowed strange constructions that would parse differently in C and C++.

Character literals are ints in C and chars in C++.

There were always valid C programs that were not valid C++.

Function declarations and definitions provide lots of examples.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Great to see a C v C++ war and the poor ASM users are not blown to bits and described as Luddites..... devil

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i don't really understand this topic, or why you even need 10 years to learn C++....

 

the most important thing is that you know how to find documentation on the subject / libraries you need for your project. Its impossible to know everything 

 

I am actually from a computer science background and work with C#, but i use java as well sometimes, and other web programming languages like php and python. Never worked with C++ but i don't think that really does matter

While C# and Java and C++ are different programming languages, they are all 3 OOP languages, the differences are mostly in the libraries and the syntax

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

js wrote:
Great to see a C v C++ war and the poor ASM users are not blown to bits and described as Luddites..... devil

 

<-- Luddite.  We gave up and went home. 

 

Fortunately there isn't avr-assembler-2014, avr-assembler-2017, avr-assembler-2020 ...

 

S.

 

PS - And yes, in carefully chosen situations, C and C++ can compile down to the exact same instructions a clever assembler coder would use, but the point is the rest of the time, not the carefully cherry-picked examples.  One:  In assembler, all the registers are available as the location of the returned value, so you don't have to 'mov' it around (or into and out of SRAM) in order to use it again in the next instruction.  Edited to add PS.  S.

 

Last Edited: Tue. Jul 25, 2017 - 01:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

zerco wrote:
Its impossible to know everything
But that is not true for C. So it comes as a shock to C programmers (who know every last detail of the language and libc) to come to C++ which apparently is so large that you would never have a hope of carrying it all around in your head.

 

Think of a carpenter and a box of tools. After 20 years experience the guy knows all of:

 

Ball-peen hammer
Boiler scaling hammer
Brass hammer
Carpenter's hammer
Cow hammer
Cross-peen hammer
Dead blow hammer
Drilling hammer
Engineer's hammer
Geologist's hammer
Joiner's hammer
Knife-edged hammer
Lathe hammer
Lump hammer
Mallets
Rounding hammer
Sledgehammer
Soft-faced hammer
Splitting maul
Stonemason's hammer
Tinner's hammer
Upholstery hammer
Welder's chipping hammer

 

He knows what each one of those is and when is the right time to go looking for a particular one. Same for spanners, screwdrivers and so on.

 

C is like that - it's a complete toolbox and the skilled engineer knows every tool in the box, when to pick one and what they can achieve.

 

C++ is more like:

 

http://craphound.com/images/009H0259000.jpeg

 

(worse in fact!). There may be some very clever tools in there with very specific jobs but if you don't know about them how are you ever going to know that they would make a particular job easier?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
(worse in fact!)

Choice of words.. "worse" or "more". The latter is more neutral.

 

Still, that's a viable picture of it. And even worse, uh, more..

 

Template meta programming is half-way to having your own forgery to make new tools if you want to. I have not explored this area much more than making myself informed enough to have an rough understanding about what it is. Never practiced it. Might be interesting as an "intellectual exercise", but I have too many things on my to-do-in-life list for it to have bubbled up to the level of "do this with an effort".

 

I believe I've read this article before, but am not sure. Looks good, but no guarantees:

 

https://www.codeproject.com/Arti... - This one has interesting stuff on letting the compiler generate an unrolled loop.

 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

whats wrong with that? 

Use what you know, and look for what you need to complete the job... 

 

there are endless of libs in C# or in the case of Java, and so it seems in the case of C++

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

zerco wrote:
whats wrong with that? 

If this was re my TMP stuff above: Nothing. It was not my intention to slam TMP in any way. I was just trying to express that it is some of the most advanced (and, for me, hard to penetrate) stuff in C++. OTOH, the newer C++ STLs offer and/or make use of it, so for anyone with a general interest in C++ it makes sense to at least be informed. I'm still working on being that.. ;-)

 

zerco wrote:
Use what you know, and look for what you need to complete the job

Agree.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Every now and then I learn something new about assembler.

 

S.

 

PS - My toolbox has a finder, a grabber, a spanner, a screwer, and a lever.  laugh  S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've concluded that C++ is not that hard, if you just focus on the language and ignore the standard library with all its bells and whistles. It also doesn't cause any particular bloat compared to C, once you understand the mechanics behind how code is generated.

 

I think it may be too flexible, there are many ways to accomplish anything, so naturally everyone and their dog writes libraries to do the same, according to their particular taste.

For example, I wrote a blink program using a class template (for Arduino style hardware), this template generates a class for every different pin that is used. It's a bit like a C macro, but better.

The generated code is the same as a C implementation would create, there is no penalty in terms of size. So, I guess I like C++.

 

#include <avr/io.h>
#include <util/delay.h>

// arbitrarly use PORT as base addres
enum base {B = (const uint16_t) &PORTB,	C = (const uint16_t) &PORTC, D = (const uint16_t) &PORTD};

template <base b, int pin_bit>
class Pin {
    // calculate offsets for DDRx and PINx
	static const int8_t dir_offset = &DDRB - &PORTB;
	static const int8_t in_offset = &PINB - &PORTB;

	public:
		static void set(){
			*(volatile uint8_t*)b |= 1<<pin_bit;
		}
		static void clear(){
			*(volatile uint8_t*)b &= ~(1<<pin_bit);
		}
		static void as_output(){
			*(volatile uint8_t*) (b + dir_offset) |= 1<<pin_bit;
		}
		static void as_input(){
			*(volatile uint8_t*) (b + dir_offset) &= ~(1<<pin_bit);
		}
		static void toggle(){
			*(volatile uint8_t*) (b + in_offset) |= 1<<pin_bit;
		}
};

int main(){
	Pin<B,5>::as_output();
	while (1) {
		Pin<B,5>::toggle();
		_delay_ms(500);
	}
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd suggest C# as a nice way to get into C++. It's much easier and more forgiving.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, and no. There are so much of syntax differences that there's a lot to forget or learn when switching fromn C# to C++.

 

The inheritance mechanism looks different. No "outlined" (as oppose to inlined) function definitions in C#. Templates are different..The "assembly" concept in .NET differs from the #include concept + linking in C++..

 

If you had said "I'd suggest C# as a nice way to get into OOP" I would agree 100%. C# or Java. Much better, IMO, to get to the principles of OO in one of those than in C++.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I would subject Python, very popular (indent are part of the language, making C codes more beautiful)

or R (is very easy , has a great help (*.txt with less, *.pdf, *.html) with examples and fuzzy search (if one needs help and makes typos...) , supports polymorphism).

The fact that R and Python supports polymorphism (ex sin(MPI) returns zero; sin(c(0, MPI/2., MPI)) returns an array of {0,1,0}) is pleasant enough and one can think it lacks in C... then, if one is not too lazy,  one goes to C++ (other advantage : Arduino) , though it is less easy...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can I just mention Python?

 

Also OOP and t may be just marginally easier to follow what is going on because "this" is not hidden". Your class functions all take "self" as the first parameter which, apart from anything else, makes it clear what are members and what aren't because they are all referenced as self.something

 

(I imagine there was a lot of to-ing and fro-ing in the design meetings for Python before they made the decision to expose that!)

 

EDIT: oops had this in the editor for 30 mins while distracted - seems I'm not the only advocate of Python ? ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am not a Python advocate :

I learned R before : this is a sujective reason;

R has better documentation than Python, with working examples (they are used for test, unless specified, if the result is stored , before installing a package/R itself)

you do not need to indent (Python is very boring in this respect); just "compile" a function, then decompile and it will get indented (if variable names are long, comments -which are lost-  may be felt as redundent).

OTOH :

R is less popular than Python (but should be, of course)

R has too many libraries (perhaps 100 for regressions / robust regressions ; python's scipy has may be one for this topic -carefully selected-)

R is meant for statistics (can be extended for geostatistics, geography...) and people think it is "only" meant for that.

 

Python is general purpose :

 

youtube-dl is coded in Python;

 

Python  calls opencv in a comfortable way http://www.pyimagesearch.com/201... ;

 

matplotlib gives very nice plots, without effort https://balau82.wordpress.com/20... )

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dbrion0606 wrote:
R has better documentation than Python, with working examples
Better than...

https://docs.python.org/3/

 

Seems difficult to believe that anything could be better - I think it's great - I learned Python almost exclusively from those pages and nothing else.