Hallo zusammen.

Na M1.R, da hast du ja was grauenvoll teuflisches entdeckt .

Ich habe mal alle Varianten zu folgendem ausprobiert mit Optimizermode "-Os" (Größe): (Versionen: avr-gcc (GCC) 4.1.2 (WinAVR 20070525))
-- Als Variable
int8_t a=0;
char a=0;

-- Als Funktion
usart_put_int (a);
usart_put_int ((int8_t) a);
usart_put_int8_t (a);

-- Als Rechnung
a=a+1;
a+=1;
a++;

Es gibt nur genau eine Funktion, die zu jeder Variablen/Rechnungs-Kombination das richtige Ergebnis liefert.
==> Das ist die Funktion usart_put_int8_t() mit dem Parametertyp int8_t

- Das casten hatte nichts gebracht und lieferte beim a++ genau das gleiche falsche Ergebnis.
- Zu jeder anderen Variablen/Funktions-Kombination, also eigentlich mit falschem Parametertyp, hatte es keinerlei Warning vom Compiler gegeben. Auch dann nicht, wenn alle Funktionen als Prototypen angegeben waren.
- In allen Fällen wurde die Variable a als 16-Bit-Zahl immer in 2 Registern gehalten.

Hier der kommentierte Output vom Compiler im Fehlerfall mit a++:
Code:
Variante 03: int8_t a++;
   int8_t a=0;
 158:	c0 e0       	ldi	r28, 0x00	; 0  <<== Byte 1 für a
 15a:	d0 e0       	ldi	r29, 0x00	; 0  <<== Byte 2 für a
      usart_put_int (a);
 15c:	ce 01       	movw	r24, r28        <<== Ein WORT wird bewegt
 15e:	c6 df       	rcall	.-116    	; 0xec <usart_put_int>
      a++;
 166:	21 96       	adiw	r28, 0x01	; 1 <<== Ein WORT wird in a addiert
Hier der kommentierte Output vom Compiler im zufällig funktionierenden Fall mit a=a+1:
Code:
Variante 01: int8_t a=a+1
   int8_t a=0;
 158:	c0 e0       	ldi	r28, 0x00	; 0  <<== Byte 1 für a
 15a:	d0 e0       	ldi	r29, 0x00	; 0  <<== Byte 2 für a
      usart_put_int (a);
 15c:	8c 2f       	mov	r24, r28         <<== EIN Byte von a für Parameter
 15e:	99 27       	eor	r25, r25         <<== Vorbelegung Byte 2 für Parameter
 160:	87 fd       	sbrc	r24, 7          <<== Vorzeichen Low-Byte a prüfen
 162:	90 95       	com	r25              <<== Vorzeichen vom Parameter auf - setzen
 164:	c3 df       	rcall	.-122    	; 0xec <usart_put_int>
      a=a+1;
 16c:	21 96       	adiw	r28, 0x01	; 1 <<== Ein WORT wird in a addiert

Weiterer Versuch mit:
volatile int8_t a=0;

Nur jetzt wird die Variable als ein Byte im Speicher gehalten. Das 2.te Byte zum Aufrufen der INT-Parameter-Funktion wird immer mit korrektem Vorzeichen erzeugt.
- Soll heissen: Es kommt immer das richtige Ergebnis zustande.


Es bleibt: Parameter müssen passen.
Es verwundert: Kein Warning vom Compiler.
Es staunt, grüßt und trinkt nun ein Bier:

Sternthaler

P.S.: Ein Versuch, so wie von Radbruch, dass alle Varianten in einem Programm getestet werden, hat vollkommen andere Verhältnisse gebracht.
Selbst mehrere Variablen mit unterschiedlichen Startwerten konnte den Optimierer meistens nicht dazu bewegen nicht doch nur immer eine Variable zu erzeugen.
Bei Radbruch wird die "falsche" Variable b wegoptimiert.

Und dann wäre da noch die "fähige" Funktion:
void usart_put_int8_t (int8_t wert)
{
usart_put_int ((int)wert);
}