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.


Is it not that case that setup() is called once and loop() is called repeatedly? i.e. that there is an unseen main() which might look like this:

void main(){
  setup();
  while(True){
    loop();
  }
}

Apologies as I'm just looking into the Arduino and have almost no C/C++ experience; I'm trying to get a handle on this loop() situation myself.


I can't comment on Dee's response. The actual code that is executed in the main loop is here:

    int main(void) {
    init();
    initVariant();

    setup();

    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }   
    return 0;
}

And yes, setup() gets called once and loop() is being called repeatedly (together with some serial stuff).