Sie sind auf Seite 1von 9

RETURN

NIGEL JONES

f e a t u r e
A ‘C’ Test: The 0x10
Best Questions for
Would-be Embedded
Programmers
Pencils up, everyone. Here’s a test to identify potential
embedded programmers or embedded programmers with potential

A
n obligatory and significant part of the seriously doubt whether I want the job in question.
recruitment process for embedded systems From the interviewer’s perspective, a test can reveal sev-
programmers seems to be the “C test.” Over eral things about the candidate. Primarily, you can deter-
the years, I have had to both take and pre- mine the level of the candidate’s knowledge of C. However,
pare such tests and, in doing so, have real- it’s also interesting to see how the person responds to ques-
ized that these tests can be informative for tions to which they don’t know the answers. Do they make
both the interviewer and interviewee. Furthermore, when intelligent choices backed up with good intuition, or do
given outside the pressure of an interview situation, these they just guess? Are they defensive when they are stumped,
tests can also be quite entertaining. or do they exhibit a real curiosity about the problem and see
From the interviewee’s perspective, you can learn a lot it as an opportunity to learn something? I find this informa-
about the person who has written or administered the test. tion as useful as their raw performance on the test.
Is the test designed to show off the writer’s knowledge of the With these ideas in mind, I have attempted to construct a
minutiae of the ANSI standard rather than to test practical test that is heavily slanted towards the requirements of embed-
know-how? Does it test ludicrous knowledge, such as the ded systems. This is a lousy test to give to someone seeking a
ASCII values of certain characters? Are the questions heavi- job writing compilers! The questions are almost all drawn
ly slanted towards your knowledge of system calls and mem- from situations I have encountered over the years. Some of
ory allocation strategies, indicating that the writer may them are tough; however, they should all be informative.
spend his time programming computers instead of embed- This test may be given to a wide range of candidates.
ded systems? If any of these are true, then I know I would Most entry-level applicants will do poorly on this test, while

Embedded Systems Programming MAY 2000 119


c test

seasoned veterans should do very well. operator becomes part of standard {


Points are not assigned to each ques- C, macros are the only portable way
tion, as this tends to arbitrarily weight of generating inline code. Inline }
certain questions. However, if you code is often necessary in embed-
choose to adapt this test for your own ded systems in order to achieve the This construct puzzles me because the
uses, feel free to assign scores. required performance level syntax doesn’t exactly spell out what’s
• Knowledge of the ternary condi- going on. Thus, if a candidate gives
Preprocessor tional operator. This operator this as a solution, I’ll use it as an
1. Using the #define statement, how would exists in C because it allows the opportunity to explore their rationale
you declare a manifest constant that compiler to produce more optimal for doing so. If their answer is basical-
returns the number of seconds in a year? code than an if-then-else sequence. ly, “I was taught to do it this way and I
Disregard leap years in your answer. Given that performance is normal- haven’t thought about it since,” it tells
ly an issue in embedded systems, me something (bad) about them.
#define SECONDS_PER_YEAR knowledge and use of this con- A third solution is to use a goto:
(60 * 60 * 24 * 365)UL struct is important
• Understanding of the need to very Loop:
I’m looking for several things here: carefully parenthesize arguments ...
to macros goto Loop;
• Basic knowledge of the #define syn- • I also use this question to start a dis-
tax (for example, no semi-colon at cussion on the side effects of Candidates who propose this are either
the end, the need to parenthesize, macros, for example, what happens assembly language programmers
and so on) when you write code such as: (which is probably good), or else they
• An understanding that the pre- are closet BASIC/FORTRAN program-
processor will evaluate constant least = MIN(*p++, b); mers looking to get into a new field.
expressions for you. Thus, it is
clearer, and penalty-free, to spell 3. What is the purpose of the preprocessor Data declarations
out how you are calculating the directive #error? 5. Using the variable a, give definitions for
number of seconds in a year, rather the following:
than actually doing the calculation Either you know the answer to this, or a) An integer
yourself you don’t. If you don’t, see Reference 1. b) A pointer to an integer
• A realization that the expression This question is useful for differentiat- c) A pointer to a pointer to an integer
will overflow an integer argument ing between normal folks and the nerds. d) An array of 10 integers
on a 16-bit machine—hence the Only the nerds actually read the appen- e) An array of 10 pointers to integers
need for the L, telling the compiler dices of C textbooks to find out about f) A pointer to an array of 10 integers
to treat the variable as a Long such things. Of course, if you aren’t g) A pointer to a function that takes an
• As a bonus, if you modified the looking for a nerd, the candidate better integer as an argument and returns an
expression with a UL (indicating hope she doesn’t know the answer. integer
unsigned long), then you are off to h) An array of ten pointers to functions
a great start. And remember, first Infinite loops that take an integer argument and
impressions count! 4. Infinite loops often arise in embedded return an integer
systems. How does you code an infinite loop
2. Write the “standard” MIN macro—that in C? The answers are:
is, a macro that takes two arguments and a) int a; // An integer
returns the smaller of the two arguments. There are several solutions to this b) int *a; // A pointer to an
question. My preferred solution is: integer
#define MIN(A,B) c) int **a; // A pointer to a
((A) <= (B) ? (A) : (B)) while(1) pointer to an integer
{ d) int a[10]; // An array of 10
The purpose of this question is to test integers
the following: } e) int *a[10]; // An array of 10
pointers to integers
• Basic knowledge of the #define Many programmers seem to prefer: f) int (*a)[10]; // A pointer to an
directive as used in macros. This is array of 10 integers
important because until the inline for(;;) g) int (*a)(int); // A pointer to a

120 MAY 2000 Embedded Systems Programming


c test
function a that takes an integer importance and benefits of localizing with an amateur. Dan Saks has exhaus-
argument and returns an integer the scope of both data and code. tively covered const in the last year,
h) int (*a[10])(int); // An array of 10 such that every reader of ESP should
pointers to functions that take an Const be extremely familiar with what const
integer argument and return an 7. What does the keyword const mean? can and cannot do for you. If you
integer haven’t been reading that column, suf-
As soon as the interviewee says “const fice it to say that const means “read-
People often claim that a couple of means constant,” I know I’m dealing only.” Although this answer doesn’t
these are the sorts of thing that one
looks up in textbooks—and I agree.
While writing this article, I consulted
textbooks to ensure the syntax was cor-
rect. However, I expect to be asked this
question (or something close to it)
when I’m being interviewed.
Consequently, I make sure I know the
answers, at least for the few hours of the
interview. Candidates who don’t know
all the answers (or at least most of them)
are simply unprepared for the interview.
If they can’t be prepared for the inter-
view, what will they be prepared for?

Static
6. What are the uses of the keyword
static?

This simple question is rarely


answered completely. Static has three
distinct uses in C:

• A variable declared static within the


body of a function maintains its
value between function invocations
• A variable declared static within a
module, (but outside the body of a
function) is accessible by all func-
tions within that module. It is not
accessible by functions within any
other module. That is, it is a local-
ized global
• Functions declared static within a
module may only be called by other
functions within that module. That
is, the scope of the function is local-
ized to the module within which it
is declared

Most candidates get the first part


correct. A reasonable number get the
second part correct, while a pitiful num-
ber understand the third answer. This is
a serious weakness in a candidate, since
he obviously doesn’t understand the

Embedded Systems Programming MAY 2000 121


c test

really do the subject justice, I’d accept to be a const pointer to a const integer mizer some additional information
it as a correct answer. (If you want the (that is, neither the integer pointed to • Code that uses const liberally is
detailed answer, read Saks’ columns— by a, nor the pointer itself may be mod- inherently protected by the compiler
carefully!) ified). If the candidate correctly answers against inadvertent coding con-
If the candidate gets the answer these questions, I’ll be impressed. structs that result in parameters
correct, I’ll ask him these supplemen- Incidentally, you might wonder why being changed that should not be.
tal questions: I put so much emphasis on const, In short, they tend to have fewer bugs
since it is easy to write a correctly func-
What do the following declarations mean? tioning program without ever using it. Volatile
const int a; I have several reasons: 8. What does the keyword volatile mean?
int const a; Give three different examples of its use.
const int *a; • The use of const conveys some very
int * const a; useful information to someone A volatile variable is one that can
int const * a const; reading your code. In effect, declar- change unexpectedly. Consequently,
ing a parameter const tells the user the compiler can make no assump-
The first two mean the same thing, about its intended usage. If you tions about the value of the variable.
namely a is a const (read-only) integer. spend a lot of time cleaning up the In particular, the optimizer must be
The third means a is a pointer to a mess left by other people, you’ll careful to reload the variable every
const integer (that is, the integer isn’t quickly learn to appreciate this extra time it is used instead of holding a
modifiable, but the pointer is). The piece of information. (Of course, copy in a register. Examples of
fourth declares a to be a const pointer programmers who use const, rarely volatile variables are:
to an integer (that is, the integer point- leave a mess for others to clean up.)
ed to by a is modifiable, but the pointer • const has the potential for generat- • Hardware registers in peripherals
is not). The final declaration declares a ing tighter code by giving the opti- (for example, status registers)

122 MAY 2000 Embedded Systems Programming


c test

• Non-automatic variables refer- • Can a parameter be both const and the code is to return the square of
enced within an interrupt service volatile? Explain. the value pointed to by *ptr.
routine • Can a pointer be volatile? However, since *ptr points to a
• Variables shared by multiple tasks Explain. volatile parameter, the compiler
in a multi-threaded application • What’s wrong with the following will generate code that looks some-
function?: thing like this:
Candidates who don’t know the
answer to this question aren’t hired. I int square(volatile int *ptr) int square(volatile int *ptr)
consider this the most fundamental { {
question that distinguishes between a return *ptr * *ptr; int a,b;
C programmer and an embedded sys- } a = *ptr;
tems programmer. Embedded folks b = *ptr;
deal with hardware, interrupts, The answers are as follows: return a * b;
RTOSes, and the like. All of these }
require volatile variables. Failure to • Yes. An example is a read-only sta-
understand the concept of volatile tus register. It is volatile because it Because it’s possible for the value
will lead to disaster. can change unexpectedly. It is of *ptr to change unexpectedly, it is
On the (dubious) assumption that const because the program should possible for a and b to be different.
the interviewee gets this question cor- not attempt to modify it Consequently, this code could return a
rect, I like to probe a little deeper to • Yes, although this is not very com- number that is not a square! The cor-
see if they really understand the full mon. An example is when an inter- rect way to code this is:
significance of volatile. In particular, rupt service routine modifies a
I’ll ask them the following additional pointer to a buffer long square(volatile int *ptr)
questions: • This one is wicked. The intent of {

124 MAY 2000 Embedded Systems Programming


c test
int a; acceptable. The element that I’m ptr = (int *)0x67a9;
a = *ptr; looking for is the use of manifest con- *ptr = 0xaa55;
return a * a; stants, together with the |= and &= ˜
} constructs A more obscure approach is:

Bit manipulation Accessing fixed memory *(int * const)(0x67a9) = 0xaa55;


9. Embedded systems always require the locations
user to manipulate bits in registers or vari- 10. Embedded systems are often character- Even if your taste runs more to the sec-
ables. Given an integer variable a, write ized by requiring the programmer to access a ond solution, I suggest the first solution
two code fragments. The first should set bit specific memory location. On a certain pro- when you are in an interview situation.
3 of a. The second should clear bit 3 of a. ject it is required to set an integer variable
In both cases, the remaining bits should be at the absolute address 0x67a9 to the value Interrupts
unmodified. 0xaa55. The compiler is a pure ANSI com- 11. Interrupts are an important part of
piler. Write code to accomplish this task. embedded systems. Consequently, many
These are the three basic responses to compiler vendors offer an extension to stan-
this question: This problem tests whether you know dard C to support interrupts. Typically, this
that it is legal to typecast an integer to new keyword is __interrupt. The following
• No idea. The interviewee cannot a pointer in order to access an code uses __interrupt to define an interrupt
have done any embedded systems absolute location. The exact syntax service routine (ISR). Comment on the code.
work varies depending upon one’s style.
• Use bit fields. Bit fields are right up However, I would typically be looking __interrupt double compute_area
there with trigraphs as the most for something like this: (double radius)
brain-dead portion of C. Bit fields are {
inherently non-portable across com- int *ptr; double area = PI * radius *
pilers, and as such guarantee that
your code is not reusable. I recently
had the misfortune to look at a driver
written by Infineon for one of their
more complex communications
chips. It used bit fields and was com-
pletely useless because my compiler
implemented the bit fields the other
way around. The moral: never let a
non-embedded person anywhere
near a real piece of hardware!
• Use #defines and bit masks. This is
a highly portable method and is the
one that should be used. My opti-
mal solution to this problem would
be:

#define BIT3 (0x1 << 3)


static int a;

void set_bit3(void) {
a |= BIT3;
}
void clear_bit3(void) {
a &= ˜BIT3;
}

Some people prefer to define a


mask together with manifest constants
for the set and clear values. This is also

Embedded Systems Programming MAY 2000 125


c test

radius; printf() often has problems with ing signed and unsigned types have all
printf(“\nArea = %f”, area); reentrancy and performance. If you operands promoted to unsigned types.
return area; missed points three and four, I would- Thus –20 becomes a very large positive
} n’t be too hard on you. Needless to integer and the expression evaluates to
say, if you got these last two points, greater than 6. This is a very important
This function has so much wrong with your employment prospects are look- point in embedded systems where
it, it’s hard to know where to start: ing better and better unsigned data types should be used fre-
quently (see Reference 2). If you get this
• ISRs cannot return a value. If you Code examples one wrong, you are perilously close to
don’t understand this, you aren’t 12. What does the following code output not getting the job.
hired and why?
• ISRs cannot be passed parameters. 13. Comment on the following code frag-
See the first item for your employ- void foo(void) ment.
ment prospects if you missed this {
• On many processors/compilers, unsigned int a = 6; unsigned int zero = 0;
floating-point operations are not int b = -20; unsigned int compzero = 0xFFFF;
necessarily re-entrant. In some (a+b > 6) ? puts(“> 6”) : /*1’s complement of zero */
cases one needs to stack additional puts(“<= 6”);
registers. In other cases, one simply } On machines where an int is not 16
cannot do floating point in an ISR. bits, this will be incorrect. It should be
Furthermore, given that a general This question tests whether you under- coded:
rule of thumb is that ISRs should stand the integer promotion rules in C—
be short and sweet, one wonders an area that I find is very poorly under- unsigned int compzero = ˜0;
about the wisdom of doing floating- stood by many developers. Anyway, the
point math here answer is that this outputs “> 6.” The This question really gets to whether
• In a vein similar to the third point, reason for this is that expressions involv- the candidate understands the impor-

126 MAY 2000 Embedded Systems Programming


c test
tance of word length on a computer. still dynamically allocate memory from This is a fun question. I stumbled
In my experience, good embedded the heap. What are the problems with across this only recently when a col-
programmers are critically aware of dynamic memory allocation in embedded league of mine inadvertently passed a
the underlying hardware and its limi- systems? value of 0 to malloc and got back a
tations, whereas computer program- valid pointer! That is, the above code
mers tend to dismiss the hardware as a Here, I expect the user to mention will output “Got a valid pointer.” I use
necessary annoyance. memory fragmentation, problems this to start a discussion on whether
By this stage, candidates are either with garbage collection, variable exe- the interviewee thinks this is the cor-
completely demoralized—or they’re cution time, and so on. This topic has rect thing for the library routine to do.
on a roll and having a good time. If it’s been covered extensively in ESP, main- Getting the right answer here is not
obvious that the candidate isn’t very ly by P.J. Plauger. His explanations are nearly as important as the way you
good, then the test is terminated at far more insightful than anything I approach the problem and the ratio-
this point. However, if the candidate is could offer here, so go and read those nale for your decision.
doing well, then I throw in these sup- back issues! Having lulled the candi-
plemental questions. These questions date into a sense of false security, I Typedef
are hard, and I expect that only the then offer up this tidbit: 15. Typedef is frequently used in C to
very best candidates will do well on declare synonyms for pre-existing data
them. In posing these questions, I’m What does the following code fragment out- types. It is also possible to use the preproces-
looking more at the way the candidate put and why? sor to do something similar. For instance,
tackles the problems, rather than the consider the following code fragment:
answers. Anyway, have fun… char *ptr;
if ((ptr = (char *)malloc(0)) == #define dPS struct s *
Dynamic memory NULL) typedef struct s * tPS;
allocation puts(“Got a null pointer”);
14. Although not as common as in non- else The intent in both cases is to define dPS
embedded computers, embedded systems do puts(“Got a valid pointer”); and tPS to be pointers to structure s. Which

Embedded Systems Programming MAY 2000 127


c test

method, if any, is preferred and why? int a = 5, b = 7, c; coding styles, the value of code
This is a very subtle question, and any- c = a+++b; reviews, and the benefits of using lint.
one who gets it right (for the right rea- Well folks, there you have it. That
son) is to be congratulated or con- This question is intended to be a light- was my version of the C test. I hope you
demned (“get a life” springs to mind). hearted end to the quiz, as, believe it had as much fun taking it as I had writ-
The answer is the typedef is preferred. or not, this is perfectly legal syntax. ing it. If you think the test is a good test,
Consider the declarations: The question is how does the compil- then by all means use it in your recruit-
er treat it? Those poor compiler writ- ment. Who knows, I may get lucky in a
dPS p1,p2; ers actually debated this issue, and year or two and end up being on the
tPS p3,p4; came up with the “maximum munch” receiving end of my own work. esp
rule, which stipulates that the compil-
The first expands to: er should bite off as big (and legal) a Nigel Jones is a consultant living in
chunk as it can. Hence, this code is Maryland. When not underwater, he can
struct s * p1, p2; treated as: be found slaving away on a diverse range
of embedded projects. He enjoys hearing
which defines p1 to be a pointer to the c = a++ + b; from readers and can be reached at
structure and p2 to be an actual struc- NAJones@compuserve.com.
ture, which is probably not what you Thus, after this code is executed, a = 6,
wanted. The second example correctly b = 7, and c = 12. References
defines p3 and p4 to be pointers. If you knew the answer, or guessed Jones, Nigel, “In Praise of the #error direc-
correctly, well done. If you didn’t tive,” Embedded Systems Programming,
Obscure syntax know the answer then I wouldn’t con- September 1999, p. 114.
16. C allows some appalling constructs. Is sider this to be a problem. I find the Jones, Nigel, “Efficient C Code for Eight-
this construct legal, and if so what does this greatest benefit of this question is that bit MCUs,” Embedded Systems
code do? it is good for stimulating questions on Programming, November 1998, p. 66.

128 MAY 2000 Embedded Systems Programming

Das könnte Ihnen auch gefallen