Variadic function help, possible bug?

(deleted)

//value = va_arg(args, uint8_t) ; // UNCOMMENTING CAUSES APPARENT HANG

I’ve not tried it, but from an example I looked at, you may have to do this:

value = (uint8_t) va_arg(args, uint16_t) ; // need a cast here since va_arg only takes fully promoted types

Source: https://linux.die.net/man/3/va_start

C promotes byte values to int values. If the function you are calling explicitly takes a byte, then in knows to only put a byte onto the stack. If it's varargs, then its going to put a 2-byte int. So any call that has a byte fails, except those ones where the byte is the last value - eg "421". In this case, the compiler still puts a 4,2,2 on the stack, but because the processor is little-endian, the first byte of that final two-byte value is the EF you expect.

(deleted)

there are no bugs in 50 years old code. only 'features'

    *fmt++;

Perhaps you meant:

    fmt++;

The code, as written, generates a pile of compiler warnings. Here it is with the warnings corrected and it produces results exactly as expected. I changed the data so the different sizes of variable had different data. That makes it easier to see that the data was being fetched from the right variable.

//#include <stdarg.h>
//#include <stdio.h>


void setup()
{
  Serial.begin(115200);


  test("421", 0x44444444, 0x2222, 0x11); // AS EXPECTED
  test("222", (uint16_t)0x2222, (uint16_t)0x2222, (uint16_t)0x2222); // AS EXPECTED
  test("444", (uint32_t)0x44444444, (uint32_t)0x44444444, (uint32_t)0x44444444); // AS EXPECTED


  test("111", 0x11, 0x11, 0x11); // NOT AS EXPECTED
  test("124", 0x11, 0x2222, 0x44444444); // NOT AS EXPECTED
  test("412", 0x44444444, 0x11, 0x2222); // NOT AS EXPECTED
  test("111", (uint8_t)0x11, (uint8_t)0x11, (uint8_t)0x11); // NOT AS EXPECTED
  test("214", (uint16_t)0x2222, (uint8_t)0x11, (uint32_t)0x44444444); // NOT AS EXPECTED
  test("412", (uint32_t)0x44444444, (uint8_t)0x11, (uint16_t)0x2222); // NOT AS EXPECTED
  test("142", (uint8_t)0x11, (uint32_t)0x44444444, (uint16_t)0x2222); // NOT AS EXPECTED
}


void loop()
{


}


void test(const char *fmt, ...)
{
  va_list args;
  uint32_t value = 0x99999999;


  Serial.print(fmt);
  Serial.print(": ");


  va_start(args, fmt);


  while (*fmt != '\0')
  {
    switch (*fmt)
    {
      case '4':
        value = va_arg(args, uint32_t);
        break;


      case '2':
        value = va_arg(args, uint16_t);
        break;


      case '1':
        value =  (byte) va_arg(args, uint16_t);
        break;
    }


    Serial.print("<"); Serial.print(value, HEX); Serial.print(">");


    fmt++;
  }
  va_end(args);


  Serial.println();
}

Output:

421: <44444444><2222><11>
222: <2222><2222><2222>
444: <44444444><44444444><44444444>
111: <11><11><11>
124: <11><2222><44444444>
412: <44444444><11><2222>
111: <11><11><11>
214: <2222><11><44444444>
412: <44444444><11><2222>
142: <11><44444444><2222>

(deleted)

(deleted)

you have to activate under file -preferences

show verbose output during compilation and compiler-warning set to all to see all error-messages

best regards Stefan

sparky961:
Perhaps, but it does work as I wrote it. Blame C.

It will work but it generates a warning message because you fetch a byte but don't use it.

/Users/john/Documents/Arduino/sketch_dec12a/sketch_dec12a.ino: In function 'void test(const char*, ...)':
/Users/john/Documents/Arduino/sketch_dec12a/sketch_dec12a.ino:69:5: warning: value computed is not used [-Wunused-value]
     *fmt++;
     ^~~~~~

(deleted)

(deleted)

(deleted)