There's too many little things to mention, they do all add up to be quite significant in the course of programming.
Here's a tiny sample of some stuff I use constantly:
Move cursor forward word at a time: w ignoring punctuation: W reverse: b B
Move cursor to next occurrence of character Z: fZ reverse: FZ
Delete forward to next occurrence of character Z: dfZ reverse: dFZ
Change forward to next occurrence of character Z: cfZ reverse: cFZ (like delete but leaves in insert mode afterwards)
Repeat latest edit from current cursor position: .
A lot of the vi commands are composable, as illustrated to some extent above.
To search for say the next line starting with void: /^void
To delete from the current line up to the next line starting with void: d/^void
Note the similarity to dfZ/fZ from above, it's not 100% consistent but most times you can take a chance composing things as you'd expect and things work correctly.
There are far more sophisticated things too of course, but I'm not writing a vim tutorial in an HN comment.
You can do things like rename a function while rearranging its arguments either file-wide, or on a number of lines, or on an interactively selected visual region, or a section selected similar to d/^void... I presume other editors have such capabilities, but I'm most familiar with vim. In vim the actual renaming and rearranging is done using a regular expression containing backreferences:
s/old_func(\([^,]*\), \([^)]*\))/new_func(\2, \1)/
You may constrain that to a subset of lines a variety of ways, and on top of that can suffix a 'c' on the end of the substitution regexp to make it conditional and you'll get a chance to interactively yay/nay the substitution at every match in the considered lines. The conditional suffix is a godsend as it lets you be fast and sloppy with your regexps and just skip the false positives.