ghost pin inputs and array values on serial monitor

I have a sketch that seems operate correctly, but I get false commands when I start serial monitor.
It sends “at+rcb=loop2.wav and at+rcb=loop9.wav” It looks like it get 2 ghost pin inputs and gets a “9” value that is not even data in the “loopbank” array. Is it a bug in serial monitor or do you see something wrong with my code?

// here is where we define the buttons that we'll use.
int buttons[] = {2, 3, 4, 5, 6, 7, 8, 9};

// Array of loop banks
int loopbank[] = {1, 1, 2, 2, 3, 3, 4, 4};

// Arrays sizes need to match number of buttons
#define NUMBUTTONS sizeof(buttons)

// we will track if a button is just pressed, just released, or 'currently pressed'
int pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

#define DEBOUNCE 10  // button debouncer, how many ms to debounce, 5+ ms is usually plenty

void setup() {
  int i = 0;
  // setup buttons as input
  for (int i = 0; i < NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT_PULLUP);
  }
  Serial.begin(9600);
}

void loop() {
  check_switches();      // check_switches will get the button state
  // Check the state of each button
  for (byte i = 0; i < NUMBUTTONS; i++) {
    // Button has just been pressed
    if (justpressed[i]) {
      justpressed[i] = 0;
      int pinVal = buttons[i];
      if (pinVal %2 == 0) {
        Serial.print("at+ply=loop");
        Serial.print (loopbank[i]);
        Serial.print (".wav\r\n");
      }
      else {
        Serial.print("at+rcb=loop");
        Serial.print (loopbank[i]);
        Serial.print (".wav\r\n");
      }
    }
  }
}

void check_switches()
{
  static int previousstate[NUMBUTTONS];
  static int currentstate[NUMBUTTONS];
  static long lasttime;
  int index;

  if (millis() < lasttime) { // millis will reset to 0 after 4 billon milliseconds, about 50 days
     lasttime = millis();
  }
  
  if ((lasttime + DEBOUNCE) > millis()) {
    // not enough time has passed to debounce
    return; 
  }
  // ok we have waited DEBOUNCE milliseconds, lets reset the timer
  lasttime = millis();
  
  for (index = 0; index < NUMBUTTONS; index++) { // when we start, we clear out the "just" indicators
    justreleased[index] = 0;
     
    currentstate[index] = digitalRead(buttons[index]);   // read the button
    
    if (currentstate[index] == previousstate[index]) {
      if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
          // just pressed
          justpressed[index] = 1;
      }
      else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
          // just released
          justreleased[index] = 1;
      }
      pressed[index] = !currentstate[index];  // remember, digital LOW means NOT pressed
    }
    previousstate[index] = currentstate[index];   // keep a running tally of the buttons
  }
}
#define NUMBUTTONS sizeof(buttons)

Start by fixing this. sizeof() returns the number of bytes used by a variable or array. An int uses 2 bytes. Can you see a problem ?

Why is buttons an int anyway ?

Nice! I switched int for byte and no more problems. Thanks!

Glad it works

A safer way to do it is

sizeof(buttons) / sizeof(buttons[0];

That form will work with any type of variable although you should always aim to use the most appropriate type and make them const too if, like the button pins, the value will never change.

Personally I have an aversion to #defines so would normally use const values