Document directory
- 1. Use the preprocessing command # define to declare a constant to indicate the number of seconds in a year (ignore the leap year problem)
- 2. Write a "standard" macro MIN, which inputs two parameters and returns a smaller one.
- 3. pre-processor ID # What is the purpose of error?
- 4. Infinite loops are often used in embedded systems. How do you write an infinite loop in C?
- 5. Use variable a to give the following definition
- 6. What is the role of the keyword static?
- 7. What does the const keyword mean?
- 8. What does the keyword volatile mean? Three different examples are provided.
- 9. In an embedded system, you must perform bit operations on variables or registers. Given an integer variable a, write two pieces of code. The first one sets bit 3 of a, and the second one clears bit 3 of. In the preceding two operations, you must keep the other bits unchanged.
- 10. embedded systems often require programmers to access a specific memory location.
- 11. interruption is an important part of embedded systems, which causes many compilation developers to provide an extension to interrupt Standard C support. The fact is that,
- 12. What is the output of the following code? Why?
- 13. Evaluate the following code snippet:
- 14. Although not as common as embedded computers, embedded systems still have the process of dynamically allocating memory from heap. In the embedded system, what are the possible problems with dynamic memory allocation?
- 15 Typedef is frequently used in C to declare an existing data type. You can also use a pre-processor to do similar things. For example, consider the following example:
- 16. The C language agrees to some shocking structures. Is the following structure legal? If so, what does it do?
This test is suitable for candidates of different levels. Most primary-level candidates have poor performance, and experienced programmers should have good performance.
In order for you to determine the preference of some questions, no score is assigned for each question. If you choose these questions for your use, please assign scores according to your meaning.
Preprocessor)
1. Use the preprocessing command # define to declare a constant to indicate the number of seconds in a year (ignore the leap year problem)
# Define SECONDS_PER_YEAR (60*60*24*365) UL
Here I want to see several things:
1) # basic knowledge of define syntax (for example, it cannot end with a semicolon, use of parentheses, and so on)
2) know that The Preprocessor will calculate the value of a constant expression for you. Therefore, you can directly write how much seconds you have in a year instead of calculating the actual value,
It is clearer with no cost.
3) realize that this expression will overflow the integer number of a 16-bit machine-so the long integer sign L is used to tell the compiler that this constant is the long integer number.
4) if you use UL (representing an unsigned long integer) in your expression, you have a good starting point. Remember, the first impression is very important.
2. Write a "standard" macro MIN, which inputs two parameters and returns a smaller one.
# Define MIN (A, B) (A) <= (B )? (A): (B ))
This test is intended for the following purposes:
1) ID # basic knowledge of define application in macros. This is important. Because before the inline operator becomes part of standard C,
Macro is the only way to easily generate embedded code. For embedded systems, to achieve the required performance, embedded code is often a required method.
2) knowledge of triple-condition operators. This operator exists in the C language because it enables the compiler to produce code that is more optimized than if-then-else,
It is important to understand this usage.
3) Be careful to enclose parameters in brackets in macros.
4) I also use this question to discuss the side effects of macros. For example, what will happen when you write down the code below?
Least = MIN (* p ++, B );
3. pre-processor ID # What is the purpose of error?
If you do not know the answer, see References 1. This problem is useful for distinguishing a normal guy from a nerd.
Only the nerd can read the appendix of the C language textbook to find the answer to such a question. Of course, if you are not looking for a nerd,
Therefore, it is recommended that you do not want to know the answer.
Infinite loops)
4. Infinite loops are often used in embedded systems. How do you write an infinite loop in C?
There are several solutions to this problem. My preferred solution is:
While (1)
{
}
Some programmers prefer the following solutions:
For (;;)
{
}
This implementation method makes me embarrassed because this syntax does not exactly express what is going on. If a candidate provides this solution,
I will use this as an opportunity to explore their basic principles. If their basic answer is: "I was taught to do this, but I never thought of why. "
This leaves a bad impression on me.
The third solution is to use goto
Loop:
...
Goto Loop;
If the candidate gives the above solution, it indicates that he is an assembly language programmer (which may be a good thing) or a BASIC/FORTRAN programmer who wants to enter a new field.
Data declarations)
5. Use variable a to give the following definition
A) An integer (An integer) int;
B) A pointer to an integer (a pointer to an integer) int *;
C) A pointer to a pointer pointing to an integer (a pointer to A pointer to an intege) int **;
D) An array of 10 integers (An array of 10 integers) int a [10];
E) an array with 10 pointers pointing to an integer. (An array of 10 pointers to integers) int * a [10];
F) A pointer (a pointer to an array of 10 integers) int (* A) [10];
G) a pointer to a function, which has an integer parameter and
Returns an integer (A pointer to a function that takes an integer as an argument and returns an integer) int (* a) (int B );
H) An array with 10 pointers pointing to a function that has an integer parameter and returns an integer number.
(An array of ten pointers tofunctions that take an integer argument and return an integer) int (* a [10]) (int B );
The answer is:
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 there are several questions that can be answered only after a book is opened. I agree with this statement.
When I wrote this article, I checked the book to confirm the correctness of the syntax. But when I was interviewed,
I expect to be asked this question (or a similar question ). Because I knew the answer to this question during the interview period.
If the examinee does not know all the answers (or at least most of the answers), the candidate will not be prepared for the interview. If the interviewer is not prepared for the interview,
Then why did he prepare?
Static
6. What is the role of the keyword static?
Few people can answer this simple question completely. In the C language, the keyword static has three obvious functions:
1) In the function body, a variable declared as static remains unchanged when the function is called.
2) in a module (but in the function body), a variable declared as static can be accessed by the function used in the module, but not by other functions outside the module.
It is a local global variable.
3) in a module, a function declared as static can only be called by other functions in the module. That is, this function is restricted to use within the local scope of the module that declares it.
Most of the respondents can answer part 1 correctly. Some of them can answer part 2 correctly. Few people can understand part 3.
This is a serious disadvantage of a candidate because he obviously does not understand the benefits and importance of localized data and code scope.
Const
7. What does the const keyword mean?
As soon as I hear the subject say, "const means constant", I know that I am dealing with an amateur. Last year, dansaks has completely summarized it in his article.
Therefore, every ESP (TRANSLATOR: Embedded systemsprogramming) reader should be very familiar with what const can and cannot do.
If you have never read that article, you only need to say that const means "read-only. Although this is not a complete answer, I accept it as a correct answer.
(If you want to know more detailed answers, read the Saks Article carefully .)
If the examinee can answer this question correctly, I will ask him an additional question:
What does the following statement mean?
Const int;
Int const;
Const int *;
Int * const;
Int const * a const;
/******/
The first two functions are the same. A is a constant integer. Third, it means that a is a pointer to a constant INTEGER (that is, an integer cannot be modified, but a pointer can be ).
Fourth, a is a constant pointer to an integer (that is, the integer to which the Pointer Points can be modified, but the pointer cannot be modified ).
The last one means that A is a constant pointer to a constant INTEGER (that is, the pointer to an integer cannot be modified, and the pointer cannot be modified ).
If the examinee can answer these questions correctly, he will leave a good impression on me. By the way, you may ask, even if you do not need the keyword const,
It is still easy to write a program with the correct function. Why do I need to pay so much attention to the keyword const? I also have the following reasons:
1) The function of the keyword const is to send very useful information to the person who reads your code. In fact, the purpose of declaring a parameter as a constant is to inform the user of the application of this parameter.
If you spend a lot of time cleaning up the garbage left by others, you will soon learn to thank this excess information. (Of course, programmers who know how to use const rarely leave garbage.
Let others clean up .)
2) by attaching some information to the optimizer, using the keyword const may produce more compact code.
3) the rational use of the keyword const can enable the compiler to naturally protect those parameters that do not want to be changed, so as to prevent them from being accidentally modified by code. In short,
This reduces the number of bugs.
Volatile
8. What does the keyword volatile mean? Three different examples are provided.
A variable defined as volatile means that this variable may be unexpectedly changed, so that the compiler will not assume the value of this variable.
Precisely, the optimizer must carefully re-read the value of this variable every time when using this variable, rather than using the backup stored in the register.
The following are examples of volatile variables:
1) Hardware registers of parallel devices (for example, Status Registers)
2) Non-automatic variables that will be accessed in an interrupt service subroutine)
3) variables shared by several tasks in multi-threaded applications
People who cannot answer this question will not be hired. I think this is the most basic problem to distinguish between C programmers and embedded system programmers. Embedded people often work with hardware,
Interrupt, RTOS, etc. All of these require volatile variables. If you do not know volatile content, it will lead to disasters.
If the subject correctly answers this question (well, I suspect this will happen), I will go over it and check whether this guy is straight forward.
Understand the full importance of volatile.
1) can a parameter be const or volatile? Explain why.
2) can a pointer be volatile? Explain why.
3); what are the following function errors:
Int square (volatile int * PTR)
{
Return * PTR ** PTR;
}
The answer is as follows:
1) Yes. One example is read-only status registers. It is volatile because it may be unexpectedly changed. It is const because the program should not try to modify it.
2); yes. Although this is not very common. One example is when a service subroutine repairs a pointer to a buffer.
3) This code is a little abnormal. The purpose of this Code is to return the pointer * PTR points to the square of the value. However, because * PTR points to a volatile parameter,
The compiler will generate code similar to the following:
Int square (volatile int * PTR)
{
Int A, B;
A = * PTR;
B = * PTR;
Return a * B;
}
* The value of * PTR may be unexpectedly changed, so a and B may be different. As a result, this Code may not return the expected square value! The correct code is as follows:
Long square (volatile int * PTR)
{
Int;
A = * PTR;
Return a *;
}
Bit manipulation)
9. In an embedded system, you must perform bit operations on variables or registers. Given an integer variable a, write two pieces of code. The first one sets bit 3 of a, and the second one clears bit 3 of. In the preceding two operations, you must keep the other bits unchanged.
There are three basic responses to this problem.
1) I don't know how to start. The quilt has never worked on any embedded system.
2) use bit fields. Bitfields is thrown into the dead corner of C language. It ensures that your Code cannot be transplanted between different compilers,
It also ensures that your Code cannot be reused. I recently unfortunately saw Infineon's driver for its more complex communication chip, which uses bit fields
It is useless to me because my compiler implements bitfields in other ways. Morality: Never let a non-embedded guy stick the actual hardware edge.
3) Use # defines and bit masks. This is a highly portable method and should be used. The best solution is as follows:
# Define BIT3 (0x1 <3)
Static int;
Void set_bit3 (void)
{
A | = BIT3;
}
Void clear_bit3 (void)
{
A & = ~ BIT3;
}
Some people like to define a mask to set and clear values and define some descriptive constants at the same time, which is acceptable. I want to see several key points:
Constant, | =, and ~ Operation.
Accessing fixed memory locations)
10. embedded systems often require programmers to access a specific memory location.
In a project, you must set an integer variable whose absolute address is 0x67a9.
The value is 0xaa66. The compiler is a pure ANSI compiler. Write code to complete this task.
Test whether you know that it is legal to forcibly convert an integer number (typecast) into a pointer to access an absolute address.
The implementation of this problem varies with the individual style. The typical code is as follows:
Int * PTR;
PTR = (int *) 0x67a9;
* PTR = 0xaa55;
A more obscure approach is:
A relatively obscure method is:
* (Int * const) (0x67a9) = 0xaa55;
Even if your taste is closer to the second option, I suggest you use the first option during the interview.
Interrupts)
11. interruption is an important part of embedded systems, which causes many compilation developers to provide an extension to interrupt Standard C support. The fact is that,
A New Keyword _ interrupt is generated. The following code uses the _ interrupt keyword to define an interrupt service subroutine (ISR ),
Please comment on this code.
_ Interrupt double compute_area (double radius)
{
Double area = pI * radius;
Printf ("/narea = % F", area );
Return area;
}
There are too many errors in this function, so people don't know where to start:
1) ISR cannot return a value. If you do not understand this, you will not be hired.
2) ISR cannot pass parameters. If you do not see this, your chances of being hired are equivalent to the first.
3) In many processors/compilers, floating points are generally not reentrant. Some processors/compilers need to import the registers at the amount into the stack,
Some processors/compilers do not allow floating-point operations in ISR. In addition, ISR should be short and efficient, and it is unwise to perform floating point operations in ISR.
4) with the 3.1 pulse, printf () often has re-import and performance problems. If you lose the third and fourth points, I won't be too embarrassed.
Needless to say, if you can get the last two points, your prospects for employment will become brighter.
Code example)
12. What is the output of the following code? Why?
Void foo (void)
{
Unsigned int a = 6;
Int B =-20;
(A + B> 6 )? Puts ("> 6"): puts ("<= 6 ");
}
This problem tests whether you understand the principle of automatic Integer Conversion in the C language. I found that some developers know very little about these things. No matter what,
The answer to this unsigned integer is "> 6 ". The reason is that when there are signed and unsigned types in the expression, all operands are automatically converted to the unsigned type.
Therefore,-20 is a very large positive integer, so the result calculated by this expression is greater than 6.
This is very important for embedded systems that should frequently use the unsigned data type. If you fail to answer this question, you will not be able to get the job.
13. Evaluate the following code snippet:
Unsigned int zero = 0;
Unsigned int compzero = 0 xFFFF;
/* 1's complement of zero */
For a 16-bit processor of the int type, the above Code is incorrect. It should be written as follows:
Unsigned int compzero = ~ 0;
This question reveals whether the examinee understands the importance of the processor font length. In my experience, good embedded programmers can understand hardware details and its limitations very accurately,
However, PC programs often treat hardware as an unavoidable headache.
At this stage, the examinee is either totally frustrated or confident. If it is clear that the candidate is not good, the test will end here.
However, if the candidates are doing well, I will throw the following append questions. These questions are difficult. I think only very good candidates can do well.
To raise these questions, I hope to see more methods for the examinee to cope with the questions, rather than the answers. In any case, you should be entertaining...
Dynamic Memory Allocation (dynamic memory allocation)
14. Although not as common as embedded computers, embedded systems still have the process of dynamically allocating memory from heap. In the embedded system, what are the possible problems with dynamic memory allocation?
Here, I expect the examinee to mention memory fragmentation, fragment collection issues, variable holding time, and so on. This topic has been widely discussed in the ESP magazine.
(Mainly p.j. plauger. His explanation is far more than any of the explanations I can mention here.) Let's look back at these magazines! Let the examinee enter a false
After feeling safe, I took out such a small program:
What is the output of the following code snippet? Why?
Char * PTR;
If (PTR = (char *) malloc (0) = NULL)
Puts ("got a null pointer ");
Else
Puts ("got a valid Pointer ");
This is an interesting question. Recently, one of my colleagues inadvertently passed the 0 value to the malloc function. After obtaining a valid pointer,
I thought of this question. This is the above Code. The output of this code is "got a validpointer ". I used this to start discussing such a problem,
Check whether the subject thinks the library routine is correct. It is important to get the correct answer, but the solution to the problem and the basic principles of your decision are more important.
Typedef
15 Typedef is frequently used in C to declare an existing data type. You can also use a pre-processor to do similar things. For example, consider the following example:
# Define DPS struct s *
Typedef struct s * TPS;
The intention of the above two cases is to define the DPS and TPS as a pointing structure s pointer. Which method is better? (If so) Why?
This is a very subtle question. Anyone should be congratulated on answering this question (the legitimate reason. The answer is: typedef is better. Consider the following example:
DPS P1, P2;
TPS P3, P4;
The first extension is
Struct s * P1, P2;
The code above defines P1 as a pointer to the structure, and P2 as an actual structure, which may not be what you want. The second example correctly defines the P3 and P4 pointers.
Obscure syntax
16. The C language agrees to some shocking structures. Is the following structure legal? If so, what does it do?
Int A = 5, B = 7, C;
C = A ++ B;
This question will end happily in this quiz. Whether you believe it or not, the above example is completely syntactic. The problem is how does the compiler handle it?
The authors of low-level compilation will actually argue about this issue. According to the best processing principle, the compiler should be able to handle as many valid usage as possible. Therefore, the above Code is processed:
C = A ++ B;
Therefore, a = 6, B = 7, c = 12 after the code is executed.
If you know the answer or guess the correct answer, you can do well. If you do not know the answer, I will not regard it as a question.
I found that the biggest advantage of this problem is that it is a good topic about the code writing style, code readability, and code modifyability.
Okay, guys. You have finished all the tests now. This is my C language test question. I wrote it with pleasure. I hope you can read it in the same mood.
If you think this is a good test, try to use it in your job search process. The Sky knows that maybe after a year or two, I will not do my current job. I also need to find one.
Introduction:
Nikel Jones is a consultant and now lives in Maryland. When he is not underwater, you can find him in multiple scope embedded projects.
He is very happy to receive a letter from the reader, his e-mail address is: NAJones@compuserve.com
References
1) Jones, Nigel, "In Praise of the # error directive," Embedded Systems Programming, September 1999, p. 114.
2) Jones, Nigel, "Efficient C Code for Eight-bit MCUs," Embedded Systems Programming, November 1998, p. 66.