vimtricks.wiki Concise Vim tricks, one at a time.

How do I jump between matching #if, #else, and #endif preprocessor directives in C code?

Answer

[#

Explanation

Vim includes built-in motions for navigating C preprocessor conditional blocks: [# jumps backward to the previous unmatched #if or #else, and ]# jumps forward to the next unmatched #else or #endif. These make it easy to orient yourself inside deeply nested conditional compilation blocks without manually searching.

How it works

  • [# — jump to the previous unmatched #if, #ifdef, #ifndef, or #else
  • ]# — jump to the next unmatched #else, #elif, or #endif
  • "Unmatched" means there is no closing counterpart at the same nesting level between the cursor and the target

Vim respects nesting depth: if you are inside a nested #ifdef, [# takes you to the enclosing boundary, not a deeper one.

Example

#ifdef PLATFORM_LINUX      ← [# lands here
  #ifdef HAVE_EPOLL        ← [# from inner block
    use_epoll();           ← cursor here
  #endif
#endif

From the cursor inside the inner block, one [# reaches #ifdef HAVE_EPOLL; pressing [# again reaches #ifdef PLATFORM_LINUX.

Tips

  • % on a #if/#else/#endif line jumps to its partner — but [#/]# work from inside the block, not on the directive line itself
  • These motions accept an operator prefix: d[# deletes from the cursor back to the unmatched #if, making it easy to cut out an entire conditional branch
  • Works with all preprocessor conditionals: #if, #ifdef, #ifndef, #elif, #else, #endif
  • See :help [# for the full list of related preprocessor jump commands

Next

How do I open the directory containing the current file in netrw from within Vim?