Was ist die Frage? Gute Frage! |
printf("%u", 123); |
printf("%u", 123 ); Der Standard bestimmt in der Beschreibung dieser Library-Funktion für %d und %u die Typen int bzw. unsigned. Der Standard kündigt undefiniertes Verhalten an, falls zu den Konversionsspezifizierern unkorrekte Typen plaziert werden. |
For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits; there shall be exactly one sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type. If the sign bit is zero, it shall not affect the resulting value. |
Bei signed Integern werden die Bits der Objektrepräsentation in drei Gruppen aufgeteilt: Wert-Bits, Padding-Bits und ein Sign-Bit. Padding-Bits sind optional; es muß kein Padding-Bit vorhanden sein. Jedes Wert-Bit soll den gleichen Wert haben wie das gleiche Bit in der Objektrepräsentation des korrespondierenden unsigned Integers. Wenn das Sign-Bit gleich 0 ist, soll es keinen Effekt auf den resultierenden Wert haben. |
(Inklusive padding-,sign- und value-Bits.) |
:Bei Funktionsaufrufen, falls wegen fehlendem Prototyp oder Angabe einer Ellipsis , ...) die Typen unbekannt sind: |
Bei Funktionsaufrufen, wenn die Typen unbekannt sind: |
[[Code] fprintf: If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined. |
Aus meiner Sicht bedeutet dies alles eine Wertaustauschbarkeit mit Ausnahme des Wertbereiches. Allerdings will ich nicht mit absolut 100%-iger Klarheit mit Ja antworten, weil eine Antwort -wie so oft- indirekt logisch hergeleitet werden muß. |
Der Standard spricht hier nicht von 'same' oder 'identical' Typ, sondern: es muß der richtige/korrekte Typ sein. ] Aus meiner Sicht bedeutet das alles eine vollkommene Austauschbarkeit mit Ausnahme des Wertbereiches. |
== Weitere Standard-Auszüge = |
== Diskussion = Es gibt hier Diskussionsbedarf: |
Man achte hier auf die Absätze 6 und 7+va_arg: |
6.5.2.2 Function calls Constraints 1 The expression that denotes the called function77) shall have type pointer to function returning void or returning an object type other than an array type. 2 If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter. Semantics 3 A postfix expression followed by parentheses () containing a possibly empty, comma- separated list of expressions is a function call. The postfix expression denotes the called function. The list of expressions specifies the arguments to the function. 4 An argument may be an expression of any object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.78) 5 If the expression that denotes the called function has type pointer to function returning an object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, the function call has type void. If an attempt is made to modify the result of a function call or to access it after the next sequence point, the behavior is undefined. 6 If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that |
6.5.2.2 Function calls Constraints 1 The expression that denotes the called function77) shall have type pointer to function returning void or returning an object type other than an array type. 2 If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter. Semantics 3 A postfix expression followed by parentheses () containing a possibly empty, comma- separated list of expressions is a function call. The postfix expression denotes the called function. The list of expressions specifies the arguments to the function. 4 An argument may be an expression of any object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.78) 5 If the expression that denotes the called function has type pointer to function returning an object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, the function call has type void. If an attempt is made to modify the result of a function call or to access it after the next sequence point, the behavior is undefined. 6 If the expression that denotes the called function has a type that does not include a prototype: ___________________________________________________________________________ the integer promotions are performed on each argument, and arguments that |
7 If the expression that denotes the called function has a type that does include a prototype, |
7 If the expression that denotes the called function has a type that does include a prototype: ___________________________________________________________________________ |
8 No other conversions are performed implicitly; in particular, the number and types of arguments are not compared with those of the parameters in a function definition that does not include a function prototype declarator. 9 If the function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function, the behavior is undefined. 10 The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call. 11 Recursive function calls shall be permitted, both directly and indirectly through any chain of other functions. |
8 No other conversions are performed implicitly; in particular, the number and types of arguments are not compared with those of the parameters in a function definition that does not include a function prototype declarator. 9 If the function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function, the behavior is undefined. 10 The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call. 11 Recursive function calls shall be permitted, both directly and indirectly through any chain of other functions. va_arg(): If there is no actual next argument, or if type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined, except for the following cases: - one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types; - one type is pointer to void and the other is a pointer to a character type. |
Absatz 6 ist offenbar fehlerhaft. |
(Absatz 6 ist offenbar fehlerhaft.) Durch die nachträglich eingefügte Gliederung ergibt sich allerdings eine weitere Interpretationsmöglichkeit. Den Absatz zu va_arg sehe ich als Fortsetzung/Ergänzung des Absatz 7. Ich stellte gerade fest, daß der Standard mit "Funktionsdefinition ohne inkludierten Prototyp" eine Art Funktionsdefinition meint, die er selbst am Ende als obsolet bezeichnet. Nämlich: void fuu(a) int a; { return; } Diese Funktionsdefinition wirkt *nicht* gleichzeitig als Prototyp für nachfolgende Aufrufe, während void fuu(int a) { return; } gleichzeitig als Prototyp fungieren kann. Der Standard bezieht sich jeweils ohne den geringsten Hinweis auf die obsolete Form und benutzt sie als Grundlage. Das rollt einem wirklich die Fußnägel hoch! Ich kann also nur erneut bekräftigen, daß man bei jeder einzelnen Frage den gesamten Standard lesen/kennen sollte. |
Frage | ![]() |
Ist folgendes möglich ohne die Gefahr von undefiniertem Verhalten?:
printf("%d", 123u); printf("%u", 123 );Der Standard bestimmt in der Beschreibung dieser Library-Funktion für %d und %u die Typen int bzw. unsigned.
Antwort | ![]() |
Aus dem C-Standard C99:
![]() |
|
![]() |
|
![]() |
|
Weitere Standard-Auszüge | ![]() |
Man achte hier auf die Absätze 6 und 7+va_arg:
![]() |
|
Ich stellte gerade fest, daß der Standard mit "Funktionsdefinition ohne inkludierten Prototyp" eine Art Funktionsdefinition meint, die er selbst am Ende als obsolet bezeichnet. Nämlich: void fuu(a) int a; { return; } Diese Funktionsdefinition wirkt *nicht* gleichzeitig als Prototyp für nachfolgende Aufrufe, während void fuu(int a) { return; } gleichzeitig als Prototyp fungieren kann.Der Standard bezieht sich jeweils ohne den geringsten Hinweis auf die obsolete Form und benutzt sie als Grundlage. Das rollt einem wirklich die Fußnägel hoch!
Ich kann also nur erneut bekräftigen, daß man bei jeder einzelnen Frage den gesamten Standard lesen/kennen sollte.