sizeof(char)

Hi all, I'm new to this forum so I don't know if this already came up.
code:

void loop()
{
  byte c = 1, d = 1;
  char buf[0x100];
  Serial.println("------------------");
  for(int i=0;i<0x200;i++) {
    sprintf(buf,"%5d,%5d,%5d,%5d",sizeof(c), c, sizeof(d), d);
    Serial.println(buf);
    c*=2;
    d++;
  }
}

output on console:

------------------
    1,    1,    1,    1
    1,    2,    1,    2
    1,    4,    1,    3
...
    1,   64,    1,    7
    1, -128,    1,    8
    1,    0,    1,    9
    1,    0,    1,   10
....
    1,    0,    1,  253
    1,    0,    1,  254
    1,    0,    1,  255
    1,    0,    1,  256
    1,    0,    1,  257
    1,    0,    1,  258
    1,    0,    1,  259

I'm a bit puzzeld about sizeof(d) returning 1 but apperantly beeing capable counting above 8-bit limit, if using postfix increment.
Maybe someone can explain the magic behind?
Thanks,
chi

I'm a bit puzzeld about sizeof(d) returning 1

"d" is a "byte", so "sizeof (d)" is 1.

oooh sorry for that. the code I posted above should read

 char c = 1, d = 1;

since that's what triggers the error (if it's an error at all).
using "byte" works as expected.
@AWOL For your answer: Yes "d" is a byte (or char in the error case) and sizeof() correctly returns 1 for both char and byte.
The topic for me is that the char with size 1 (what I assume to be 8 bits?) counts above 255, a behaviour that I can't reproduce on other toolsets.

The topic for me is that the char with size 1 (what I assume to be 8 bits?) counts above 255, a behaviour that I can't reproduce on other toolsets.

A byte of char will increment to zero after 255.

Lefty

I'm a bit puzzeld ...

I'm puzzled too. As retrolefty points out - a byte should increment to 0 after 255, but apparently it does not.

One could argue that your format statement is wrong:

sprintf(buf,"%5d,%5d,%5d,%5d",sizeof(c), c, sizeof(d), d);

"%d" is a placeholder for a 16 bit signed integer and this contradicts the 8 bit integers you pass as arguments. A more correct rewrite would look as follows:

uint8_t c;
int8_t d;

sprintf(buf,"%5u,%5u,%5u,%5d",sizeof(c), (uint16_t)c, sizeof(d),(int16_t)d);

I tried this however and the output is still not what I expected. This may possibly be related to optimization in that c and d are promoted to 16 bit quantities at compile time which is needed when they're passed as arguments to sprintf.

Still I can't really see this as anything but a bug and something the AVR GCC dvelopers may want to look at.

@BenF: that's exactly what I am thinking about this issue, just wanted to hear other opinions.
about sprintf args: as I remember all integral varargs to printf are promoted to int upon call automatically, but that shouldn't change the underlying type of the variable. AND as you may see from the code snippet this bug happens if postincrement (d++) is used. the other var "c", declared with the same type, that is modified using "=2" wraps at 255 as expected. seems like an optimization issue for mee too.

I checked AVR Toolchain Bugs and found several issues at least one dating back to 2007 that deal with mis-optimization of 8 bit data. The one that hits best is probably 33970 – Missed optimization using unsigned char loop variable.
seems it needs a volunteer.
chi

33970 – Missed optimization using unsigned char loop variable
Missed optimization using unsigned char loop variable

An "unsigned char" is a "byte". This bug isn't related.

It looks like the code generator completely eliminates the variable d. The compiler must recognize that the value of d is always i+1 and substitute i+1 for d.