Last updated:2026-10-12
How to Read Open Source C++ Code¶
How to Instantly Understand Open Source Project Code¶
In real projects or open source code — especially C code — macros are used a lot, which creates a big problem: reading the code becomes very difficult, and debugging is another issue. Given a project full of macros, how do you understand it quickly?
In interviews we often run into a very important knowledge point: the gcc compilation process. Most people can rattle off the answer, so to distinguish candidates' levels, it extends into: which gcc compilation flags do you know, and what does each of them do? What happens during the preprocessing stage? What do you usually do at this stage, and how does it help you?
This section uses an open source project as the example: how to understand the code in seconds!
Below is a piece of libev code containing several macros, such as:
- EV_FREQUENT_CHECK
- assert
EV_P_- ANHE_w
- ANHE_at_cache
void noinline
ev_timer_start (EV_P_ ev_timer *w) EV_THROW
{
if (expect_false (ev_is_active (w)))
return;
ev_at (w) += mn_now;
assert (("libev: ev_timer_start called with negative timer repeat value", w->repeat >= 0.));
EV_FREQUENT_CHECK;
++timercnt;
ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);
array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);
ANHE_w (timers [ev_active (w)]) = (WT)w;
ANHE_at_cache (timers [ev_active (w)]);
upheap (timers, ev_active (w));
EV_FREQUENT_CHECK;
/*assert (("libev: internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/
}
Looks confusing at first glance, right? This snippet raises a few questions:
- How many parameters does the function take?
- What is the function's type?
- What on earth is ev_at in the code?
To understand the code in seconds, we need to use -E to get the code after macro expansion in the preprocessing stage, which makes it easier to understand and read.
After expansion, we get:
void __attribute__ ((__noinline__))
ev_timer_start (struct ev_loop *loop, ev_timer *w)
{
if (__builtin_expect ((!!((0 + ((ev_watcher *)(void *)(w))->active))),(0)))
return;
((WT)(w))->at += ((loop)->mn_now);
# 3881 "ev.c" 3 4
((
# 3881 "ev.c"
("libev: ev_timer_start called with negative timer repeat value", w->repeat >= 0.)
# 3881 "ev.c" 3 4
) ? (void) (0) : __assert_fail (
# 388libev: ev_timer_start called with negative timer repeat value\", w->repeat >= 0.)"
# 3881 "ev.c" 3 4
, "ev.c", 3881, __PRETTY_FUNCTION__))
# 3881 "ev.c"
;
do { } while (0);
++((loop)->timercnt);
ev_start (loop, (W)w, ((loop)->timercnt) + (4 - 1) - 1);
if (__builtin_expect ((!!((((W)(w))->active + 1) > (((loop)->timermax)))),(0))) { int __attribute__ ((__unused__)) ocur_ = (((loop)->timermax)); (((loop)->timers)) = (ANHE *)array_realloc (sizeof (ANHE), (((loop)->timers)), &(((loop)->timermax)), (((W)(w))->active + 1)); ; };
(((loop)->timers) [((W)(w))->active]).w = (WT)w;
(((loop)->timers) [((W)(w))->active]).at = (((loop)->timers) [((W)(w))->active]).w->at;
upheap (((loop)->timers), ((W)(w))->active);
do { } while (0);
}
At this point we can understand the code with basically no obstacles, but it is still not clear enough. To highlight the difference between you and other candidates, I'll pose a few questions:
- The output above shows a lot of line-number lines; can they be removed, and how would you solve it?
- System macros like assert above are very simple and easy to understand, so we don't need to expand them — do you know how to do that?
- Problems may occur during these two expansion steps; do you know what happens and how to fix it?
Alright, that's all for this section. The next section will continue the discussion — welcome to talk about the answers above in the comments!
Related Topics¶
- Six Ways to Split Strings in C++ | C++那些事
- CPython Extension Development Notes | C++那些事
- libcurl C++ Development Notes | C++那些事
- An Interesting Piece of C++ Code | C++那些事
- Printing 1-100 in C++ Without Loops | C++那些事