embedded software boot camp

A ‘C’ Test: The 0×10 Best Questions for Would-be Embedded Programmers (reprised)

Tuesday, September 15th, 2009 by Nigel Jones

In May 2000 Embedded Systems Programming magazine (now Embedded Systems Design) published an article I had written entitled “A ‘C’ Test: The 0×10 Best Questions for Would-be Embedded Programmers.”

A revised version is posted at: A ‘C’ Test: The 0×10 Best Questions for Would-be Embedded Programmers.

I received a lot of mail about it at the time (including a decent amount of hate mail), and, much to my amazement, I continue to get mail about it to this day. The article has been shamelessly copied all over the web and its title is a popular search term that drives people to this blog.

Be aware that this test has been widely publicized, so be very suspicious of someone that does really well on it! To illustrate my point, when I wrote the article I was doing some work at a large company and was sharing an office with a fellow consultant, Nelson. Naturally I had Nelson proof read the article. Fast forward a few months when Nelson went off to an interview with a new potential client. Well it so happens that the interview occurred on the same day that my article was published, and the interviewer proceeded to use it verbatim on Nelson. Nelson, of course, aced the test leaving the interviewer astounded. Needless to say, we both found this to be very amusing! Alas, I’ve never had anyone in the intervening 9+ years hit me with it. Maybe next week…

If you would like a version of this test in Word format, or could use some expertise from an embedded systems consultant, please contact me.

Tags:

9 Responses to “A ‘C’ Test: The 0×10 Best Questions for Would-be Embedded Programmers (reprised)”

  1. Peter Butler says:

    Your 0×10 best questions for would-be embedded programmers may overstate answer 6b. You say, “A variable declared static within a module … is accessible by all functions within that module.void f1(void) return ci+3;static int ci = 6;void f2(void) return ci+4;Will this compile? I would expect that ci would be unknown to f1(). In my understanding const vs. #define is mostly a scope issue.Your 0×10 best questions … is why I favor assembly code. I KNOW what is going on. No odd compiler or language strangeness. But to be fair I use C/C++ as appropriate. Consider fragments of code used to generate DTMF tones. I used (ARM Cortex-M3) assembly code to form (signed int) 2^24*sin(x) where x is an unsigned 32-bit integer = r*(2^32)/(2*pi) and r is in radians. I.e. x/(2^32) is the fraction of the way around a circle. I wanted 12-bit accuracy (any more would be wasted) and I needed abs(sin(x)) < 1.0 for all x. Truncating the Taylor series at x^7/7! gave me both speed and the desired accuracy.Code calling my assembly code was in C. I added appropriate constants to two variables, called my sin function twice and added the results. The result went into a software FIFO which in retrospect likely should have been written in C. The ISR playing the tone was in assembly. It could have been written in C but any processor change (even a different vendors Cortex-M3) would require changes. When it came time to write DTMF decode I used C and vendor-provided 32-bit software floating point. This was WAY easier than implementing the Goertzel algorithm in 8051 assembly.

  2. GregK says:

    HiNice job.I am thinking about other example to question 0×8. your example b is:"Non-stack variables referenced within an interrupt service routine."I think "Non-stack" is not appropriate. Memory allocated from stack do not differ specially than allocated during compile time. I am able image situation where thread allocate some memory on stack, pass pointer to this memory to IRQ, by global pointer, or signal from global queue. There are other methods, some RTOS using dispatcher to resolve/dispatch IRQ request, if so than routine can have argument or queue associated with IRQ to pass information. So IRQ eventually will using memory allocated from stack of other thread.What You think?

  3. Nigel Jones says:

    Peter:You are correct about the scope of static. That being said, anyone that does this deserves what will inevitably happen the first time the code gets refactored. Indeed you can take this a step further. I think it was reader 'Uhmmmmmm' that pointed out that one can indeed call a static function from another module (translation unit to be very precise), by simply calling it via a function pointer. Will this work? – sure, is it nuts? – yes.I find your statement about assembly language mostly true, but a strange justification for its use. (Note that I say this as someone who enjoys assembly language programming). For example, while it is in general true that with assembly language what you see is what you get,in my experience one soon starts resorting to higher level features in an assembler (such as parametrized macros, data structures, 'built-in' functions etc), and that these are even more language specific than 'standard' C.Now I am highly sympathetic to the use of assembly language for performance reasons. For example, I recently ranted about the lack of a 3 byte integer in most embedded C compilers that forces one to do perform operations on 4 byte integers when 3 bytes would do just fine. That being said, it's rare that I find myself in a CPU constrained situation, and so I find the need for assembly language to be diminishing. I might say that I think this is a bad thing, because until one has done assembly language programming, one can never really understand what is going on 'under the hood'.

  4. Nigel Jones says:

    GregK:To the best of my knowledge, the only variables allocated on the stack by a C compiler are function parameters and so called automatic variables (non statically allocated function variables declared at function scope). The key thing about these variables is that they have highly limited scope and also a highly limited lifetime. Now you can always abuse such variables by taking their address and passing this address to other code to dereference. I predict disaster if you do though.Incidentally, the example you quoted sounds to me more like a case where memory would be allocated from the heap.

  5. GregK says:

    HiOf course I am not going use such technique at all. It is not resist critique. It is just an example. I just wanted to discuss, it is rather academic discussion if it proper place. Probably not :) , we are focusing on practical approaching.Of course disaster is close, but is in programmer responsibility to use this technique proper, and compiler responsibility to compliant with standard.But I am actually not sure of this code:void generic_thread(void * parm){ volatile data_t p; global_p = &p; /* is it possible to optimise and roll stack here????????? I doubt it can. we reference this variable below. but better do not relay on it. */ int tab[10]; for(;;) /* main loop */ { sleep(1); if (p.something) { } }}//However volatile in functions is really useful for debugging purpose under high optimization level. Very often you can not see value of variable under debugger. volatile (just in debug compilation) is better then write to global variable, since global variable could be optimized even though is not static (good compilers and linkers can do this).

  6. Darren says:

    I just thought I would point out a discussion about the original 2000 article currently generating a lot of traffic in the "Real-Time Embedded Engineering" group on LinkedIn. I can't see a static link so here is a link to the group and the discussion

  7. Nigel Jones says:

    Thanks Darren. I had noticed the traffic. I've applied to join the group and will attempt to contribute to the discussion. That being said I'm just about to head out on a business trip so my time may be limited in the very near future.

  8. Ian Johns says:

    > one can indeed call a static function from another module (translation unit to be very precise), by simply calling it via a function pointer. Will this work? – sure, is it nuts? – yes

    It isn’t nuts at all. For instance, an application could use a callback handler/manager that executes functions via pointers when certain configured events occur. A module may configure an event callback passing one of its own private/static functions. So although the static function may execute only when called via function pointer by the external callback handler, the static function may only be directly accessed/configured/etc. by its own module.

    This type of callback mechanism is very useful & usage with static functions is not unreasonable.

    • Gauthier says:

      I second that. You can have a module register a static function for running at a timer interrupt, as a more specific example.
      The function is not directly callable from outside, besides by the module it is registered to.

Leave a Reply