Fundamentals 19 min read

Essential C Interview Questions for Embedded Systems: Preprocessor, Macros, and More

This article compiles a comprehensive set of embedded‑C interview questions covering preprocessors, macros, infinite loops, data declarations, static, const, volatile, bit manipulation, fixed‑address memory access, interrupts, code snippets, dynamic allocation, typedefs and obscure syntax, each with detailed explanations and example code.

ITPUB
ITPUB
ITPUB
Essential C Interview Questions for Embedded Systems: Preprocessor, Macros, and More

Preprocessor

Define a constant for the number of seconds in a year using #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL. The discussion highlights basic #define syntax, the benefit of letting the preprocessor compute constant expressions, the need for unsigned long suffix to avoid overflow on 16‑bit targets, and the use of UL as a good practice.

It also asks for a standard MIN macro that returns the smaller of two arguments, emphasizing the importance of parenthesising parameters: #define MIN(A,B) ((A) <= (B) ? (A) : (B)). The purpose is to test knowledge of macro side‑effects and proper argument handling.

Infinite Loops

Common ways to write an infinite loop in embedded C are shown: while(1) { }, for(;;) { }, and a goto Loop; label. The article notes how each style reveals the candidate’s understanding of low‑level control flow.

Data Declarations

Eight declaration tasks are presented, from a simple integer to pointers to functions. The correct answers are:

int a;
int *a;
int **a;
int a[10];
int *a[10];
int (*a)[10];
int (*a)(int);
int (*a[10])(int);

static Keyword

Three effects of static in C are explained: (1) a function‑local static variable retains its value between calls, (2) a file‑scope static variable is visible only within that translation unit, and (3) a static function is limited to the defining file.

const Keyword

The article stresses that const means “read‑only” and is more than just a constant. It examines several declarations such as const int a;, int const a;, const int *a;, int * const a;, and const int * const a;, explaining which parts are immutable. Benefits of const include clearer intent, possible optimizer improvements, and reduced bugs.

volatile Keyword

volatile

tells the compiler that a variable may change unexpectedly, preventing certain optimizations. Typical examples are hardware registers, variables accessed in an ISR, and shared variables in multithreaded code. The article also answers questions about combining const and volatile, volatile pointers, and why a function like int square(volatile int *ptr) must avoid using the volatile value twice in an expression.

Bit Manipulation

To set and clear bit 3 of an integer a while preserving other bits, the recommended portable solution uses masks:

#define BIT3 (0x1 << 3)
static int a;
void set_bit3(void) { a |= BIT3; }
void clear_bit3(void) { a &= ~BIT3; }

Accessing Fixed Memory Locations

For an absolute address 0x67A9, the straightforward ANSI‑C method is:

int *ptr = (int *)0x67A9;
*ptr = 0xAA55;

An alternative, more obscure form is *(int * const)(0x67A9) = 0xAA55;, but the first version is recommended in interviews.

Interrupts

The article critiques a sample ISR declared as __interrupt double compute_area(double radius), pointing out four major errors: an ISR cannot return a value, cannot take parameters, floating‑point operations are often non‑reentrant, and using printf inside an ISR is unsafe.

Code Examples

A snippet illustrating integer promotion rules:

void foo(void) {
    unsigned int a = 6;
    int b = -20;
    (a + b > 6) ? puts("> 6") : puts("<= 6");
}

The expression evaluates to “> 6” because b is converted to an unsigned value, yielding a large positive number.

Dynamic Memory Allocation

When malloc(0) is called, the implementation may return a non‑NULL pointer; the article shows a test that prints “Got a valid pointer”. It also discusses typical concerns in embedded systems such as fragmentation and lifetime of allocated blocks.

typedef vs. #define

Using typedef to create an alias for a pointer type is safer than a macro because the macro can lead to unintended declarations (e.g., struct s *p1, p2; makes p2 a struct, not a pointer). The typedef version correctly defines both p3 and p4 as pointers.

Obscure Syntax

The expression c = a+++b; is legal and parsed as c = a++ + b;, resulting in a becoming 6, b staying 7, and c being 12 after execution.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

CMemoryinterview-questionsembedded systemsMacrosPreprocessor
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.