C Language Interview Questions: In-Depth Analysis of Essential Embedded Knowledge

Click the blue text above: IoT Guesthouse to follow us

In embedded C language interviews, in addition to basic syntax and data structures, some advanced features such as macro definitions, storage classes, and type modifiers will also be emphasized. These knowledge points not only test your mastery of syntax but also your understanding of the underlying mechanisms of the C language.

01Macro Definitions and Comparison

1Using define to implement comparison

Question: Implement a function using macro definitions to compare the sizes of two integers.

#define MAX(a, b) ((a) > (b) ? (a) : (b))

Analysis: The comparison is implemented using the ternary operator. Note the use of parentheses to avoid issues with operator precedence during macro expansion.

2Side Effects of Macro Definitions

Question: What is the output of the following code?

#define MAX(a, b) ((a) > (b) ? (a) : (b)) int main() {         int x = 5, y = 10;         printf("%d\n", MAX(x++, y));         return 0; }

Answer: 5

Analysis: After macro expansion, it becomes ((x++) > (y) ? (x++) : (y)), where x++ is evaluated twice, leading to x being modified twice.

02Storage Classes and Scope

3Function of static

What are the effects of static inside and outside functions?

// Outside function static int global_var = 10;  // Inside function void func() {         static int local_var = 20; }

Analysis:

  • Outside function A global variable modified by static is only visible within the file where it is defined, limiting the variable’s scope.
  • Inside function A local variable modified by static retains its value between function calls, and initialization occurs only once.

4Static and Lifetime

Question: What is the output of the following code?

void func() {         static int count = 0;         count++;         printf("%d\n", count); } int main() {         func();         func();         return 0; }

Answer: 1, 2

Analysis: The static local variable count retains its value between function calls; count is 1 on the first call and 2 on the second call.

5Function of extern

Question: How to share global variables across multiple files?

// file1.c int global_var = 10;  // file2.c extern int global_var;

Analysis: extern is used to declare a variable or function, indicating that the variable or function is defined in another file. By using extern to declare global_var in file2.c, it can access global_var defined in file1.c.

03Type Modifiers

6Function of const

Question: What is the output of the following code?

void func(const int* p) {         *p = 10; // Error } int main() {     int a = 5;     func(&a);     return 0; }

Answer: Compilation error

Analysis: const int* p indicates that the value pointed to by p cannot be modified. Attempting to modify the value through p will result in a compilation error.

7Correct usage of const, how to use const to modify pointers?

void func(const int* p) {     printf("%d\n", *p); }

Analysis: const int* p indicates that the value pointed to by p cannot be modified, but p itself can be modified. If you want to prevent modification of p itself, use const int* const p.

8Function of volatile

What is the function of volatile?

volatile int flag = 0;

Analysis: A variable modified by volatile tells the compiler not to optimize these variables, ensuring that each access to the variable reads from memory rather than using the value in registers. It is commonly used in scenarios such as hardware registers and interrupt service routines.

9Typical application of volatile

Question: What is the output of the following code?

volatile int flag = 0; void isr() {   flag = 1; } int main() {   while (!flag) {         // Wait for interrupt to set the flag   }   printf("Interrupt occurred\n");   return 0; }

Answer: Interrupt occurredAnalysis: The variable flag modified by volatile ensures that it is read from memory each time, avoiding an infinite loop caused by compiler optimization.

04Memory and Size

10Difference between sizeof and strlen

What is the difference between sizeof() and strlen()?

char str[] = "Hello"; printf("sizeof(str) = %zu\n", sizeof(str)); printf("strlen(str) = %zu\n", strlen(str));

Answer: sizeof(str) = 6, strlen(str) = 5

Analysis:

  • sizeof is an operator that returns the size (in bytes) of a variable or type, including the string terminator \0.
  • strlen is a function that returns the actual length of the string (excluding the terminator \0).

11Application of sizeof

Question: How to dynamically allocate an array and initialize it?

int size = 5; int* arr = (int*)malloc(size * sizeof(int)); for (int i = 0; i < size; i++) {     arr[i] = i; }free(arr);

Analysis: sizeof(int) is used to calculate the size of each element, ensuring that the dynamically allocated memory is sufficient to store the array elements.

12sizeof and Structure Alignment 1

Question: What is the size of the following structure?

struct {     char a;     int b; } s; printf("sizeof(s) = %zu\n", sizeof(s));

Answer: sizeof(s) = 8 (assuming 4-byte alignment)

Analysis: The structure member a occupies 1 byte, and b occupies 4 bytes, but due to alignment requirements, the total size of the structure is 8 bytes.

13sizeof and Structure Alignment 2

For embedded systems, if byte alignment is specified, the result may differ. What is the size of the following structure?

#pragma  pack(1) struct {     char a;     int b; } s;#pragma  pack() printf("sizeof(s) = %zu\n", sizeof(s));

Answer: sizeof(s) = 5 (1-byte alignment has been set)

Analysis: The structure member a occupies 1 byte, b occupies 4 bytes, and the total size of the structure is 5 bytes.

05CPU Endianness

14Code to determine CPU endianness

int is_small_endian() {     union {         unsigned int x;         char c;     } u;      u.x = 1; // Assign the integer part to 1     return u.c; // If the lowest byte is 1, it is little-endian }

Analysis:Union is a special data type that allows different data types to share the same memory space.

In this example,u.x and u.c share the same memory space.

  • Assignment Assigning u.x to 1. In memory, the value of u.x is 0x00000001 (assuming a 32-bit integer).
  • Accessing the lowest byte Accessing the lowest byte of u.x through u.c. Little-endian mode The lowest byte (lowest address) stores 0x01, so u.c has the value 0x01.Big-endian mode The lowest byte (lowest address) stores 0x00, so u.c has the value 0x00.

06Spotting Errors

15Identify the errors in the following function

_interrupt double compute_ares(double radius) {   double area = PI * radius *radius;   printf(ā€œ\nArea = %dā€, area);   return area; }

Analysis:

1. Incorrect return type; interrupt functions are generally void type functions;

2. Calling complex functions is incorrect; printf is a complex function that may involve significant stack operations and system calls;

3. The format string contains an error with %d; floating-point types should use %f for formatting;

4. Performing floating-point operations in interrupt context is incorrect; floating-point operations are generally slower than integer operations and may increase interrupt handling time.

07Conclusion

If you have any questions during use, please join the QQ group for further communication.

QQ group: 573122190 (Note: IoT project communication)

C Language Interview Questions: In-Depth Analysis of Essential Embedded KnowledgeENDPrevious HighlightsWonderfulReview01 | Vehicle Environment Detection Instrument Based on RT_Thread and ML30202 | Smart Watering System Based on STM32 and WeChat Mini Program03 | Award-winning Work of RTT Competition: Multifunctional Alarm Clock Based on W601Scan to follow usC Language Interview Questions: In-Depth Analysis of Essential Embedded KnowledgeFocusing on WeChat Mini Program IoT solutions.We guide you step by step in exploring the Internet of Things!

Leave a Comment