Seite 1 von 1

C - printf - Adresse ausgeben mit %p

Verfasst: 10.08.2022, 11:21
von starcow
Ich bin auf folgende Diskussion gestossen, im Zusammenhang mit const.

Code: Alles auswählen

printf("&A = %p\n",&A);
I'd recommend a cast to a pointer to void if you're using the %p conversion specifier. Sure it might seem to work how it's supposed to on most implementations even without the cast, but to be pedantic, this is undefined behavior.
The %p conversion specifier expects a pointer to void, and if any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

From the C standard draft n1570 (The fprintf function) (didn't write exactly where it is in the standard draft, because YouTube doesn't seem to like it if you put a lot of numbers in your comment) (emphasis mine):
p The argument shall be a **pointer to void**. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.
Stimmt das tatsächlich? Ist es ohne den cast nach void pointer ein "undefined behavior"? Müsste ich also immer in einen void pointer casten, ehe ich eine Adresse ausgebe?

Code: Alles auswählen

int x;
printf("%p", (void*)&x);
Gruss starcow

Re: C - printf - Adresse ausgeben mit %p

Verfasst: 10.08.2022, 12:04
von Schrompf
Standards kann ich Dir nicht sagen, aber ich weiß, dass jeder Pointer implizit zu void* konvertiert. Und die varargs, die u.A. bei printf() verwendet werden, haben ein eigenes Set an Konvertierungsregeln. Wer weiß, ob da was drin steht, was alle Pointer automatisch zu void* konvertiert?

Re: C - printf - Adresse ausgeben mit %p

Verfasst: 10.08.2022, 12:23
von Krishty
Es stimmt. Die Ausgabe von %p erfordert void *. Variable Parameterlisten promoten zwar ihre Operanden (so dass etwa aus short automatisch ein int wird), ändern aber nicht den Typ von Zeigern. Das hat man offen gelassen, weil der C-Standard dem Compiler Spielraum bei der Implementierung von Zeigern gibt, und deshalb ein int * nicht zwingenderweise identisch einem void * ist (weder in Größe noch Inhalt).

Beachte, dass das wirklich ein Detail von %p ist, und nicht an der variablen Parameterlist liegt – wenn du bspw. scanf() nutzt, um ein int zu füllen, musst du sogar einen int * ohne Cast zu void * übergeben.

(P.S.: Ist eine Erklärung, aber keine Rechtfertigung. Ich hasse diesen Cast. Aber auch ich muss mich dran halten.)

Re: C - printf - Adresse ausgeben mit %p

Verfasst: 10.08.2022, 15:44
von starcow
Puuh! Ok, gut zu wissen! Danke euch.

Re: C - printf - Adresse ausgeben mit %p

Verfasst: 21.08.2022, 15:46
von starcow
Kann das sein, dass Carmack in seinem Talk mit Lex genau dieses Problem als eine der Hauptursachen von Bugs in ihrem eigenen Code nennt? :-)

https://youtu.be/I845O57ZSy4?t=3802

Kontext:
https://youtu.be/I845O57ZSy4?t=3408

Re: C - printf - Adresse ausgeben mit %p

Verfasst: 21.08.2022, 21:02
von Krishty
Nicht speziell %p, aber durchaus genau diese Klasse von Bugs, ja.