Skip to main content

10 Classic Embedded C Interview Questions Explained

·678 words·4 mins
C Embedded Memory Management Security
Table of Contents

In embedded systems, C remains the dominant language due to its deterministic behavior and direct hardware access. That same power also makes it dangerous: small mistakes in pointer handling or memory management can crash systems, corrupt data, or create security vulnerabilities.

The following 10 classic interview questions are frequently used to assess whether a developer truly understands C at a system level.

⚠️ The Danger of gets()
#

Question: Identify the issue in the following code:

#include <stdio.h>

int main(void)
{
    char buff[10];
    memset(buff, 0, sizeof(buff));

    gets(buff);   // Problematic line
    printf("The buffer entered is [%s]\n", buff);
    return 0;
}

Answer: gets() performs no bounds checking. If the input exceeds the buffer size, it causes a stack-based buffer overflow, overwriting adjacent memory. This function is so dangerous that it has been removed from the C standard.

Correct approach: Use fgets() with an explicit length limit.


πŸ”“ Exploiting strcpy()
#

Question: Can you bypass the password protection below without knowing the password?

#include <stdio.h>

int main(int argc, char *argv[])
{
    int flag = 0;
    char passwd[10];
    memset(passwd, 0, sizeof(passwd));

    strcpy(passwd, argv[1]);

    if (strcmp("LinuxGeek", passwd) == 0)
        flag = 1;

    if (flag)
        printf("Password cracked\n");
    else
        printf("Incorrect password\n");

    return 0;
}

Answer: Yes. strcpy() does not validate destination size. A carefully crafted input longer than 10 bytes can overflow passwd and overwrite the adjacent flag variable on the stack, setting it to a non-zero value and bypassing authentication.

This is a textbook stack overflow exploit.


🧩 The Return Type of main()
#

Question: Is this valid C?

void main(void) { }

Answer: It may compile on some embedded toolchains, but it is non-standard. The C standard requires:

int main(void)

In hosted systems, the return value is passed to the operating system. Even in bare-metal systems, using int main() ensures portability and correctness.


🧠 Memory Leaks vs Program Exit
#

Question: Does this leak memory?

char *ptr = malloc(10);
return;

Answer: Yesβ€”while the program is running. Once the process terminates, the OS reclaims memory.

However, in embedded systems or long-running tasks, this pattern inside loops will exhaust the heap, leading to crashes or undefined behavior.


πŸ’₯ Modifying the Base Pointer
#

Question: Why does this crash for input "freeze" but not "zebra"?

while (*ptr != 'z') {
    ptr++;
}
free(ptr);

Answer: free() must receive the exact pointer returned by malloc(). Incrementing ptr changes its value. Passing a modified pointer to free() causes undefined behavior, often a segmentation fault.

Always preserve the original base pointer.


πŸšͺ _exit() vs exit()
#

Question: Why is the cleanup handler not called?

atexit(func);
_exit(0);

Answer: _exit() terminates the process immediately, bypassing:

  • atexit() handlers
  • I/O buffer flushing
  • Standard cleanup routines

Use exit() or return from main() if cleanup is required.


🧬 void* and Generic Interfaces
#

Question: How can a function accept arguments of any type?

Answer: Use a void * pointer. For multiple parameters, encapsulate them in a structure.

int my_function(void *args);

This technique underpins APIs like pthread_create() and callback interfaces.


βž• Operator Precedence: *ptr++
#

Question: What does this print if ptr points to "Linux"?

printf("%c", *ptr++);

Answer:

  • First call prints: L
  • Second call prints: i

Postfix ++ has higher precedence than *, but the dereference happens before the increment due to postfix semantics.

Equivalent to:

*(ptr++);

🧱 Read-Only Memory Segments
#

Question: Why does this crash?

char *ptr = "Linux";
*ptr = 'T';

Answer: String literals are typically stored in read-only memory (RODATA). Writing to them triggers a memory protection fault.

Correct usage:

char ptr[] = "Linux";
ptr[0] = 'T';

πŸ“€ Returning Addresses of Local Variables
#

Question: Why is this incorrect?

int *func(void)
{
    int a = 10;
    return &a;
}

Answer: a resides on the stack. Once the function returns, its stack frame is destroyed. The returned pointer references invalid memory, leading to undefined behavior.

Only return:

  • Heap-allocated memory
  • Static variables
  • Caller-provided buffers

βœ… Conclusion
#

These questions expose the sharp edges of Cβ€”pointer arithmetic, memory ownership, stack lifetime, and undefined behavior. Mastery of these concepts is essential for building reliable, secure embedded systems, and they remain a reliable litmus test in technical interviews.

Related

Embedded C: Double Pointers Explained
·625 words·3 mins
C Pointer Embedded
Debugging Memory Overwrite Issues in Embedded C
·601 words·3 mins
C Embedded Memory Debugging
NULL vs nullptr in Modern C++: What Developers Should Know
·537 words·3 mins
C C++ NULL Nullptr