|
|
Embedded System
Interview Questions
Preprocessor
1. Using the #define statement, how would you declare a manifest constant
that returns the number of seconds in a year? Disregard leap years in your
answer.
#define SECONDS_PER_YEAR
(60 * 60 * 24 * 365)UL
I'm looking for several things here:
• Basic knowledge of the #define syntax (for example, no semi-colon at the end,
the need to parenthesize, and so on)
• An understanding that the pre-processor will evaluate constant expressions for
you. Thus, it is clearer, and penalty-free, to spell out how you are calculating
the number of seconds in a year, rather than actually doing the calculation
yourself
• A realization that the expression will overflow an integer argument on a
16-bit machine-hence the need for the L, telling the compiler to treat the
variable as a Long
• As a bonus, if you modified the expression with a UL (indicating unsigned
long), then you are off to a great start. And remember, first impressions count!
2. Write the "standard" MIN macro-that is, a macro that takes two arguments
and returns the smaller of the two arguments.
#define MIN(A,B)
((A)
<
= (B) ? (A) : (B))
The purpose of this question is to test the following:
• Basic knowledge of the #define directive as used in macros. This is important
because until the inline operator becomes part of standard C, macros are the
only portable way of generating inline code. Inline code is often necessary in
embedded systems in order to achieve the required performance level
• Knowledge of the ternary conditional operator. This operator exists in C
because it allows the compiler to produce more optimal code than an if-then-else
sequence. Given that performance is normally an issue in embedded systems,
knowledge and use of this construct is important
• Understanding of the need to very carefully parenthesize arguments to macros
• I also use this question to start a discussion on the side effects of macros,
for example, what happens when you write code such as:
least = MIN(*p++, b);
3. What is the purpose of the preprocessor directive #error?
Either you know the answer to this, or you don't. If you don't, see Reference 1.
This question is useful for differentiating between normal folks and the nerds.
Only the nerds actually read the appendices of C textbooks to find out about
such things. Of course, if you aren't looking for a nerd, the candidate better
hope she doesn't know the answer.
Infinite loops
4. Infinite loops often arise in embedded systems. How does you code an
infinite loop in C?
There are several solutions to this question. My preferred solution is:
while(1)
{
ý
}
Many programmers seem to prefer:
for(;;)
{
ý
}
This construct puzzles me because the syntax doesn't exactly spell out what's
going on. Thus, if a candidate gives this as a solution, I'll use it as an
opportunity to explore their rationale for doing so. If their answer is
basically, "I was taught to do it this way and I haven't thought about it
since," it tells me something (bad) about them.
A third solution is to use a goto :
Loop:
...
goto Loop;
Candidates who propose this are either assembly language programmers (which is
probably good), or else they are closet BASIC/FORTRAN programmers looking to get
into a new field.
Data declarations
5. Using the variable a, give definitions for the following:
a) An integer
b) A pointer to an integer
c) A pointer to a pointer to an integer
d) An array of 10 integers
e) An array of 10 pointers to integers
f) A pointer to an array of 10 integers
g) A pointer to a function that takes an integer as an argument and returns an
integer
h) An array of ten pointers to functions that take an integer argument and
return an integer
The answers are:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument
and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an
integer argument and return an integer
People often claim that a couple of 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 correct. 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 interview, 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 functions within that module. It is not
accessible by functions within any other module. That is, it is a localized
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 localized 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 number understand the third answer. This is a
serious weakness in a candidate, since he obviously doesn't understand the
importance and benefits of localizing the scope of both data and code.
Const
7. What does the keyword const mean?
As soon as the interviewee says "const means constant," I know I'm dealing
with an amateur. Dan Saks has exhaustively covered const in the last year, such
that every reader of ESP should be extremely familiar with what const can and
cannot do for you. If you haven't been reading that column, suffice it to say
that const means "read-only." Although this answer doesn't really do the subject
justice, I'd accept it as a correct answer. (If you want the detailed answer,
read Saks' columns-carefully!)
If the candidate gets the answer correct, I'll ask him these supplemental
questions:
What do the following declarations mean?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
The first two mean the same thing, namely a is a const (read-only) integer. The
third means a is a pointer to a const integer (that is, the integer isn't
modifiable, but the pointer is). The fourth declares a to be a const pointer to
an integer (that is, the integer pointed to by a is modifiable, but the pointer
is not). The final declaration declares a to be a const pointer to a const
integer (that is, neither the integer pointed to by a, nor the pointer itself
may be modified). If the candidate correctly answers these questions, I'll be
impressed. Incidentally, you might wonder why I put so much emphasis on const,
since it is easy to write a correctly functioning program without ever using it.
I have several reasons:
• The use of const conveys some very useful information to someone reading your
code. In effect, declaring a parameter const tells the user about its intended
usage. If you spend a lot of time cleaning up the mess left by other people,
you'll quickly learn to appreciate this extra piece of information. (Of course,
programmers who use const , rarely leave a mess for others to clean up.)
• const has the potential for generating tighter code by giving the optimizer
some additional information
• Code that uses const liberally is inherently protected by the compiler against
inadvertent coding constructs that result in parameters being changed that
should not be. In short, they tend to have fewer bugs
More Embedded System Interview Questions
|
|