Formatting variables from a variadic function
With the format "ci", the argument is interpreted as an integer, and
the output is correct: 49 is the ASCII code of '1'.

With the format "cc", the argument is interpreted as a string (pointer to an
array of chars), which is incorrect.

One (bad) solution is to use the "cc" format and pass &amp;btnPressed as
an argument. The problem with this approach is that the byte in memory
right after btnPressed may not be a zero, and the format expects a
NUL-terminated string.

A better approach would be to have one format for a char and a
different one for a string. I suggest "c" and "s" respectively. But
then you should be aware that there are special promotion rules
associated with variadic functions. When playing with your code, the
compiler reminded me of this one:


  warning: ‘char’ is promoted to ‘int’ when passed
  through ‘...’


So the function should expect an int, and cast it to char in order
to call the correct overload of Serial.print():

void printConcatLine(const char* mask, ...) {
    va_list params;
    va_start(params, mask);

    while(*mask != '\0') {
      if (*mask == 'i') {
          Serial.print(va_arg(params, int));
      } else if(*mask == 's') {
          Serial.print(va_arg(params, const char *));
      } else if(*mask == 'c') {
          Serial.print((char) va_arg(params, int));
      } else if (*mask == 'f' || *mask == 'd') {
          Serial.print(va_arg(params, double));
      } 
      ++mask;    
    }

    va_end(params);
    Serial.println();
}


Used like this:

printConcatLine("sc", "BtnPressed: ", btnPressed); 
// Output: "BtnPressed: 1"