Why doesn't my code work in a function, yet works inline?
The problem is that you are passing the value of the ports to the function, not the address of the ports.

You need to either pass "by reference" or as a pointer, so that modifying the port variable modifies the actual port variable not the copy of the value that you pass.

The simplest way is to modify your function to be:

void shiftOutFast(volatile uint8_t &amp;dataPort, uint8_t dataBit,
                  volatile uint8_t &amp;clkPort, uint8_t clkBit, 
                  uint8_t bitOrder, uint8_t val) {
....
}


That way, instead of passing whatever is in the port at the time to the function (pass by value) it instead creates a new variable which is located at the same address as the variable that you are passing (pass by reference) so modifications of one variable modifies the other.

Note that only the "port" variables need to be passed by reference, all the others remain as pass by value.  Also they should be, as Edgar says, flagged as volatile.