Trying to understand Arduino Serial and C++ arrays

Hello everyone,

I've done a bit of programming for the Arduino before, but I'm not well versed in the C++ language. I come from the C# world, and I found a behaviour that is utterly alien to me.

I want to share my sketch and my serial output with you in the hope that you can enlighten me as to why I get those very strange values when I write to the last element in the char array.

The sketch is just a way to adjust the time between the blinks by sending a message through the serial port. It should be a string of the type "a__v____" ending in \n.

int ledPin = 13;
char blinkStr[4] = {0};
char pinNo[2] = {0};
char b[9];
int i = 0;
unsigned long blinkStep = 2000UL;
unsigned long blinkTime = 200UL;
unsigned long nextStep = 0UL;
bool ledStatus = false;


void setup()
{
  Serial.begin(9600);
  Serial.setTimeout(5000);
  pinMode(ledPin, OUTPUT);
}


void loop()
{
  if (Serial.available())
  {
    b[i] = Serial.read();
    i++;
    if (i == 9 || b[i - 1] == '\n' || b[i - 1] == '\r')
    {
      if ((char)b[0] == 'a' && (char)b[3] == 'v')
      {
        pinNo[0] = b[1];
        pinNo[1] = b[2];
        int newPin = atoi(pinNo);
        ledPin = newPin;
        Serial.print(blinkStr);
        Serial.print(" ");
        Serial.println(blinkStr[0]);
        blinkStr[0] = b[4];
        Serial.print(blinkStr);
        Serial.print(" ");
        Serial.println(blinkStr[0]);
        blinkStr[1] = b[5];
        Serial.print(blinkStr);
        Serial.print(" ");
        Serial.println(blinkStr[1]);
        blinkStr[2] = b[6];
        Serial.print(blinkStr);
        Serial.print(" ");
        Serial.println(blinkStr[2]);
        blinkStr[3] = b[7];
        Serial.print(blinkStr);
        Serial.print(" ");
        Serial.println(blinkStr[3]);
        int newDuration = atoi(blinkStr);
        blinkStep = newDuration;
        Serial.print("New step for pin ");
        Serial.print(pinNo);
        Serial.print(" is ");
        Serial.println(blinkStr);
        Serial.print("Parsed values are ");
        Serial.print(newPin);
        Serial.print(" and ");
        Serial.println(newDuration);
      }
      else
      {
        Serial.print("Bad buffer syntax: ");
        Serial.println(b);
      }
      i = 0;
    }
  }
  // blink loop
  if ((long)(millis() - nextStep) >= 0)
  {
    if (ledStatus == false)
    {
      digitalWrite(ledPin, HIGH);
      ledStatus = true;
      nextStep += blinkTime;
    }
    else
    {
      digitalWrite(ledPin, LOW);
      ledStatus = false;
      nextStep += blinkStep - blinkTime;
    }
  }
}

Now the fun part comes when I show you the serial output for "a13v1500":

1 1
15 5
150 0
150013a13v1500
	 0
New step for pin 13a13v1500
	 is 150013a13v1500
	
Parsed values are 13 and 18941

As you can see, the blinkStr values ar perfectly ok until I write to the last position, at which point something leaks and I get blinkStr, pinNo and the whole b array in one go. Of course, after parsing the value it wraps around the maximum integer vaule a few times and ends up at 18941.

My question is simple, why does this happen? I can prevent this by increasing their size by 1 (blinkStr[5] pinNo[3]) but I don't understand why this happens. I mean the array is of size 4. not of size 4+2+9. Why would their values leak into each other?

int newPin = atoi(pinNo);atoi accepts a string, doesn't it?

As far as I understand it, a string is actually a null terminated char array. As opposed to a String which is an object. And atoi() accepts my char array.

I'm guessing that my pinNo[2] and blinkStr[4] have no room for the final null character so they leak into each other. And that's why when I change to pinNo[3] and blinkStr[5] they work.

Thanks for the pointer.

simplethemind:
As far as I understand it, a string is actually a null terminated char array. As opposed to a String which is an object. And atoi() accepts my char array.

I'm guessing that my pinNo[2] and blinkStr[4] have no room for the final null character so they leak into each other. And that's why when I change to pinNo[3] and blinkStr[5] they work.

Thanks for the pointer.

...and thank you for accepting it, and figuring it out

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.