Re: Languages for embedded



On Sun, 21 Oct 2007 20:53:13 +0100, moschops <moschop@xxxxxxxxxxxxxx>
wrote in comp.arch.embedded:

I'm new to coding embedded software. It's been something of a baptism of
fire; I was handed a nice quad-TigerSHARC board and asked to make it
work in an environment it was never designed for (it was meant to be
inside a PC - instead I've created an environment for it electrically
identical to the one it would see inside the PC, but inside something
else entirely) and it's actually starting to do stuff.

My coding experience is mostly C++; I'm using VDSP++ ver 4.0 (the
version supported by the board manufacturer's libraries) and my code is
essentially C++ with a careful lack of classes and templates such that
it will compile as C, if you see what I mean. I've no doubt a hardened C
coder would want to change a lot of my code, much as I find my keyboard
fingers twitching when reading their code.

There are some old-school embedded coders at my workplace who mumble
about how C++ is not really a real-time language and that C is better
for such applications. I can certainly understand not using something
with automatic garbage collection (you never know for sure when
everything will pause for the memory to be cleaned up, as I understand
it), but why avoid C++? Is there something about the classes and
templates that makes it unsuitable for embedded software? What affects
the decision to use a given language for embedded coding? I'd be
grateful to hear about reasons for/against other languages besides C and
C++.

While I'm here, is there any embedded lisp out there? I'm a secret lisper.

Your secret is safe with me.

As for the C versus C++ debate, there are quite a few issues here.

Perhaps the biggest downside to C++, in the context of embedded
systems, particularly smaller, resource constrained embedded systems,
is that it has features that provide a much higher level of
abstraction. That can mean you can inadvertently add a lot of
overhead to your code.

If, inside a function, I define:

struct xyz my_xyz;

....in C, I know that a sufficient size area of memory is allocated in
automatic object space (usually the hardware stack) with generally
zero overhead, as the function entry prolog just adds the number of
bytes in the structure to the value it uses to adjust the stack
pointer which it is doing anyway.

In C++, on the other hand, even a lowly structure can have a
constructor, and the definition of an instance of the structure xyz
might call a construction that does any amount of work, including
calling constructors of the structure's members.

If I want to know whether xyz had a constructor, and how much work it
might be doing just because I want to instantiate a local object, I
need to dig into its header and perhaps source code. If an object has
a constructor, there is absolutely no way that I can create one
without it being executed.

On the other hand, if I have a C struct xyz, and the API provides a
call to initialize it such as:

SUCCESS_CODE initialize_xyz(struct xyz *xyz_ptr);

....then I have to explicitly write that code to call that function if
I need that initialization, and I can skip that call if I don't need
the standard or default initialization. At the very least, I can't
code this function call and not realize that it has some overhead,
although again I have to look at the function's source to see how
much.

The other area of confusion in C++ does not merely apply to embedded
systems, but it is the ease of confusing reference versus value
arguments to functions.

If function f() takes an int by value, it can't modify any int value
in my calling function. If f() takes an int by reference, it can
modify that value, and either way my code looks the same:

void myfunc(void)
{
int x = get_value();
f(x);
}

If f() has side effects that are the main reason for calling it, one
might forget that it also modifies the value passed to it by
reference.

You can't make that mistake when passing a pointer:

void myfunc(void)
{
int x = getvalue();
f(&x);
}

The & is a dead give away. The compiler will not accept the code if I
leave it out, so I must know it is there. If I need to have the value
returned by getvalue() intact after calling f(), I will refer to its
documentation to see if it truly modifies the value. And if so, I can
change the code to:

int x = getvalue();
int y = x;
f(&y);

....and know that x will still will still have its value after f()
returns.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
.



Relevant Pages

  • Re: Initialization: = or () ?
    ... Is either form preferable for some reason I don't ... When you have a class that has a constructor, copy constructor, all sorts of ... SuperClass(unsigned int); ... Are you not then calling the: ...
    (comp.lang.cpp)
  • Re: returning values from a class?
    ... That's not calling a class, its invoking a constructor to create a temporary ... int calculate ...
    (comp.lang.cpp)
  • Re: Initialization: = or () ?
    ... > When you have a class that has a constructor, copy constructor, all ... > Are you not then calling the: ... You're calling the SuperClass(unsigned int) constructor, ... However, a decent compiler will ...
    (comp.lang.cpp)
  • Re: Calling another constructor from a constructor
    ... > int j; ... > Is there any way of calling another constructor from a ... > constructor to initialize your object? ... with a default argument (defaulting to 0 in your case)? ...
    (comp.lang.cpp)
  • Re: Problem with linker
    ... but to have actually written a default constructor. ... such as overloading on int and pointer types. ... conversion of 0 to CString requires a user-defined conversion, ... acceleration operator *(distance d, time_squared t2); ...
    (microsoft.public.vc.mfc)