inttypes und format specifier

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
king-crash
Beiträge: 740
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

inttypes und format specifier

Beitrag von king-crash » 09.05.2014 09:10:42

Folgender Code

Code: Alles auswählen

#include <stdio.h>
#include <inttypes.h>


int main(int argc, char **argv)
	{
	uint8_t test;
	const char str[] = "abc123def";

	sscanf(str, "abc%"PRIu8"def", &test);
	printf("%"PRIu8"\n", test);

	return 0;
	}
Gibt den Fehler
test.c: In function ‘main’:
test.c:10:2: warning: format ‘%u’ expects argument of type ‘unsigned int *’, but argument 3 has type ‘uint8_t *’ [-Wformat=]
sscanf(str, "abc%"PRIu8"def", &test);
Ich hab mal im Header nachgeschaut und da ist alles ohne Modifizierer angegeben, also PRIu8 -> "u".
Für meinen Geschmack sollte das doch als "hhu" definiert sein...

Steh ich auf dem Schlauch oder ist das Header kompletter Müll?

newdeb
Beiträge: 134
Registriert: 03.02.2011 11:11:21
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Frankfurt

Re: inttypes und format specifier

Beitrag von newdeb » 09.05.2014 10:28:55

Die Debian/GNU - inttypes.h enthält Makros für Printing und Scanning Formate:
/* Macros for printing format specifiers. */
...
/* Unsigned integers. */
# define PRIu8 "u"
...
/* Macros for scanning format specifiers. */
...
/* Unsigned decimal notation. */
# define SCNu8 "hhu"
Der C99-Standard sagt:
The following macros shall be defined. Each expands to a character string literal containing a conversion specifier, possibly modified by a length modifier,
(http://pubs.opengroup.org/onlinepubs/00 ... pes.h.html)
Die Implementierer dürfen sich offenbar gewisse Freiheiten herausnehmen.

Benutzeravatar
king-crash
Beiträge: 740
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: inttypes und format specifier

Beitrag von king-crash » 14.05.2014 09:52:05

Hm die Sache ist doch aber merkwürdig.
Gehen wir mal vom printf aus

Code: Alles auswählen

uint8_t var = 1;
printf("%"PRIu8, var);
Beim Funktionsaufruf wird ein Byte auf den Stack geschoben aber der Funktion durch "%u" suggeriert es wären 4.
Oder werden bei x86 immer 4 Byte gepusht? Wenn ich mal Zeit habe werf ich den Disassembler an...

newdeb
Beiträge: 134
Registriert: 03.02.2011 11:11:21
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Frankfurt

Re: inttypes und format specifier

Beitrag von newdeb » 14.05.2014 11:19:33

Der Format-Spezifizierer beeinflusst die Ausgabe, nicht die Übergabe der Inhalte in der variablen Argumentliste in printf.
Letzteres sollten die va_* Makros (STDARG(3)) korrekt erledigen, auch unter Beachtung der Parametertypen.

wanne
Moderator
Beiträge: 7548
Registriert: 24.05.2010 12:39:42

Re: inttypes und format specifier

Beitrag von wanne » 14.05.2014 12:06:03

Code: Alles auswählen

#include <stdio.h>
#include <inttypes.h>


int main(int argc, char **argv)
{
   uint8_t test;
   const char str[] = "abc123def";

   sscanf(str, "abc%"SCNu8"def", &test);
   printf("%"PRIu8"\n", test);

   return 0;
}
rot: Moderator wanne spricht, default: User wanne spricht.

Benutzeravatar
king-crash
Beiträge: 740
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: inttypes und format specifier

Beitrag von king-crash » 14.05.2014 13:44:32

Soweit mir bekannt ist expandiert va_arg(typ) zu etwas wie salopp hole_bytes_vom_stack(sizeof(typ)).
D.h. eigentlich holt die printf Funktion anhängig vom Formatspezifizierer eine gewisse Anzahl Bytes vom Stack.
Also bei "%hhd" 1 und bei "%d" 4.
Wenn ich jetzt ein uint8 oder char nur 1 Byte übergebe aber mit "%d" 4 Bytes vom Stack hole müsste es doch krachen...

Habe ich da einen Denkfehler?

newdeb
Beiträge: 134
Registriert: 03.02.2011 11:11:21
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Frankfurt

Re: inttypes und format specifier

Beitrag von newdeb » 14.05.2014 14:28:45

king-crash hat geschrieben:Habe ich da einen Denkfehler?
Nein, würde ich nicht sagen, aber die Compiler machen da geheimnisvolle Dinge, genannt "default argument promotions":
Since the prototype doesn't specify types for optional arguments, in a call to a variadic function the default argument promotions are performed on the optional argument values. This means the objects of type char or short int (whether signed or not) are promoted to either int or unsigned int, as appropriate; and that objects of type float are promoted to type double. So, if the caller passes a char as an optional argument, it is promoted to an int, and the function can access it with va_arg (ap, int).
http://www.gnu.org/software/libc/manual ... adics.html

Benutzeravatar
king-crash
Beiträge: 740
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: inttypes und format specifier

Beitrag von king-crash » 14.05.2014 17:52:36

Ah sehr interessant, besten Dank.
Obwohl ich das Verhalten als mittelschweren Schwachsinn bezeichnen würde, insbesondere hinsichtlich der float zu double konvertierung.

Deshalb auch der Unterschied zum SCN, da hier über Pointer direkt auf die richtigen Größen zugegriffen werden muss.

Antworten