How do functions outside of void loop work?
The setup() and loop() functions are unusual because they are called automatically for you by the Arduino code. No other functions behave this way.

Generally speaking, a function will never run unless you explicitly call it yourself (e.g. from within setup() or loop()), or instruct another part of the program to call it. (There are other ways to execute functions, but that usually involves some very advanced tinkering which is best avoided.)

For example, pinMode() is a function just like any other. It only runs when you actually put something like pinMode(3, INPUT) in your code. At that point, it runs once, finishes, and then the calling function carries on from where it left off (they never run in parallel).

The example code you've posted is quite interesting. Look at these lines in setup():

Wire.onReceive(receiveData);
Wire.onRequest(sendData);


These lines are telling the Wire object to call receiveData() and sendData() in response to I2C events. It does this by passing function pointers which are stored and used by Wire.

I'd recommend searching for information about C/C++ function pointers online if you want to learn more about this. You may also be interested to explore Arduino's attachInterrupt() function.