Offene Cee FAQ / Korrespondierende Integer
 
StartSeite | OffeneCeeFAQ/ | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

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.
Der Standard kündigt undefiniertes Verhalten an, falls zu den Konversionsspezifizierern unkorrekte Typen plaziert werden.

Antwort

Aus dem C-Standard C99:

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.
Eine gültige Objekt-Repräsentation (non-trap) eines signed Integer
mit sign==0 soll gleichzeitig eine gültige Objekt-Repräsentation
des korrespondierenden unsigned Integer sein und den gleichen Wert
repräsentieren.

Bei Funktionsaufrufen, falls wegen fehlendem Prototyp oder Angabe einer Ellipsis , ...) die Typen unbekannt sind:
Wenn die Typen von Argument und korrespondierendem Parameter
nicht kompatibel sind, liegt undefiniertes Verhalten vor,
mit folgenden Ausnahmen:
    o  Wenn der eine Typ ein signed Integer ist und der andere
       der korrespondierende unsigned Integer und der übergebene
       Wert in beiden repräsentiert werden kann.
    o  ... 
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ß.

Weitere Standard-Auszüge

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
     have type float are promoted to double. These are called the default argument
     promotions. If the number of arguments does not equal the number of parameters, the
     behavior is undefined. If the function is defined with a type that includes a prototype, and
     either the prototype ends with an ellipsis (, ...) or the types of the arguments after
     promotion are not compatible with the types of the parameters, the behavior is undefined.
     If the function is defined with a type that does not include a prototype, and the types of
     the arguments after promotion are not compatible with those of the parameters after
     promotion, the behavior is undefined, except for the following cases:
     - one promoted type is a signed integer type, the other promoted type is the
         corresponding unsigned integer type, and the value is representable in both types;
     - both types are pointers to qualified or unqualified versions of a character type or
         void.
7
If the expression that denotes the called function has a type that does include a prototype:
___________________________________________________________________________
     the arguments are implicitly converted, as if by assignment, to the types of the
     corresponding parameters, taking the type of each parameter to be the unqualified version
     of its declared type. The ellipsis notation in a function prototype declarator causes
     argument type conversion to stop after the last declared parameter. The default argument
     promotions are performed on trailing arguments.
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.)
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.


StartSeite | OffeneCeeFAQ/ | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 28. September 2002 2:22 (diff))
Suchbegriff: gesucht wird
im Titel
im Text