[...]
**********************************************************************
Alle Zitate aus dem Standard gelten jeweils zusammengenommen
als Teil jeder meiner Antworten.
Es ist ein Fakt, daß zu vielen Fragestellungen zu C
jeweils ein großer Teil des Standards herangezogen werden muß.
Es kommen zwangsläufig Mehrfachnennungen vor.
Die meisten, die sich mit C beschäftigen, kommen damit nicht
klar, und erwarten zu _jeder_ Fragestellung eine separate
und spezialisierte Antwort des Standards, die es nicht
gibt und auch nicht geben kann.
**********************************************************************
Post by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongPost by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongHier widerspreche ich aufgrund von 6.3.2.3 Pointers.
Es werden stets die Bytes eines Objekts/Elements gezählt.
Ein Pointer zeigt stets auf den Objektbeginn (in Byte), sofern
zuvor keine Cast-Manipulationen an ihm stattfanden.
(uintptr_t)a ist aber eben kein Pointer, sondern ein Integer.
Das erschreckt mich nicht besonders.
===========================================================================
6.3.2.3 Pointers
Any pointer type may be converted to an integer type.
Except as previously specified, the result is implementation-defined.
If the result cannot be represented in the integer type, the behavior
is undefined.
The result need not be in the range of values of any integer type.
A pointer to an object type may be converted to a pointer to a different
object type.
If the resulting pointer is not correctly aligned68) for the referenced
type, the behavior is undefined.
Otherwise, when converted back again, the result shall compare equal
to the original pointer.
When a pointer to an object is converted to a pointer to a character type,
the result points to the lowest addressed byte of the object.
Successive increments of the result, up to the size of the object, yield
pointers to the remaining bytes of the object.
67) The mapping functions for converting a pointer to an integer
or an integer to a pointer are intended to be consistent
with the addressing structure of the execution environment.
===========================================================================
Der Standard knüpft _nicht nur hier_ eine
Verbindung zwischen Pointer/Adressen und Zahlen.
Oben werden Bytes abgezählt, die Adressen haben.
Konversionen Ptr<>Int sollen auch sinnvoll funktionieren.
Except as previously specified:
Vorbehaltlich vorhergehender Spezifikationen
===========================================================================
6.5.6 Additive operators
The result of the binary + operator is the sum of the operands.
The result of the binary - operator is the difference resulting
from the subtraction of the second operand from the first.
For the purposes of these operators, a pointer to an object
that is not an element of an array behaves the same as a pointer
to the first element of an array of length one with the type
of the object as its element type.
When an expression that has integer type is added to or subtracted
from a pointer, the result has the type of the pointer operand.
If the pointer operand points to an element of an array object, and
the array is large enough, the result points to an element offset
from the original element such that the difference of the subscripts
of the resulting and original array elements equals the integer
expression.
In other words, if the expression P points to the i-th element
of an array object, the expressions (P)+N (equivalently, N+(P)) and
(P)-N (where N has the value n) point to, respectively, the i+n-th
and i−n-th elements of the array object, provided they exist.
Moreover, if the expression P points to the last element of an
array object, the expression (P)+1 points one past the last element
of the array object, and if the expression Q points one past
the last element of an array object, the expression (Q)-1 points
to the last element of the array object.
If both the pointer operand and the result point to elements
of the same array object, or one past the last element of the
array object, the evaluation shall not produce an overflow;
otherwise, the behavior is undefined.
If the result points one past the last element of the array object,
it shall not be used as the operand of a unary * operator
that is evaluated.
When two pointers are subtracted, both shall point to elements
of the same array object, or one past the last element
of the array object; the result is the difference of the subscripts
of the two array elements.
The size of the result is implementation-defined, and its type
(a signed integer type) is ptrdiff_t defined in the <stddef.h> header.
If the result is not representable in an object of that type, the
behavior is undefined.
In other words, if the expressions P and Q point to, respectively, the
i-th and j-th elements of an array object, the expression (P)-(Q) has
the value i−j provided the value fits in an object of type ptrdiff_t.
Moreover, if the expression P points either to an element of an
array object or one past the last element of an array object, and the
expression Q points to the last element of the same array object, the
expression ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and
as -((P)-((Q)+1)), and has the value zero if the expression P
points one past the last element of the array object, even though the
expression (Q)+1 does not point to an element of the array object.106)
106) Another way to approach pointer arithmetic is first to convert
the pointer(s) to character pointer(s): In this scheme the
integer expression added to or subtracted from the converted pointer
is first multiplied by the size of the object originally pointed to, and
the resulting pointer is converted back to the original type.
For pointer subtraction, the result of the difference between the
character pointers is similarly divided by the size of the object
originally pointed to.
When viewed in this way, an implementation need only provide
one extra byte (which may overlap another object in the program)
just after the end of the object in order to satisfy the
‘‘one past the last element’’ requirements.
===========================================================================
Auch vorstehend wird die Lückenlosigkeit eines Arrays definiert.
Weiterhin, daß ein Array aus Elementen eines bestimmten Typs besteht.
Die Elemente sind daher gleich groß: sizeof(element-typ)
Die Adressen des jeweils ersten Byte der Elemente liegen
um sizeof(element-typ) auseinander.
Das konvergiert mit den Integer-Werten im Array[subscript].
ptrdiff_t ist implementations-definiert.
Ja, aber w a s ist hier implementations-definiert?
Nur sizeof(ptrdiff_t) -- sonst nichts!
===========================================================================
7.20.1.4 Integer types capable of holding object pointers
The following type designates a signed integer type with the property
that any valid pointer to void can be converted to this type, then
converted back to pointer to void, and the result will compare equal
to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property
that any valid pointer to void can be converted to this type, then
converted back to pointer to void, and the result will compare equal
to the original pointer:
uintptr_t
These types are optional.
===========================================================================
Die vorstehende Überschrift sollte genau begriffen werden!
Fußnote 67) ist wichtig.
Das nachfolgende Zitat (6.5.8) ist wichtig.
Etc.
===========================================================================
6.5.8 Relational operators
When two pointers are compared, the result depends on the relative
locations in the address space of the objects pointed to.
If two pointers to object types both point to the same object, or both
point one past the last element of the same array object, they compare equal.
If the objects pointed to are members of the same aggregate object,
pointers to structure members declared later compare greater than pointers
to members declared earlier in the structure, and pointers to array elements
with larger subscript values compare greater than pointers to elements
of the same array with lower subscript values.
All pointers to members of the same union object compare equal.
If the expression P points to an element of an array object and the
expression Q points to the last element of the same array object, the
pointer expression Q+1 compares greater than P.
In all other cases, the behavior is undefined.
===========================================================================
===========================================================================
6.5.9 Equality operators
Two pointers compare equal if and only if both are null pointers, both are
pointers to the same object (including a pointer to an object and
a subobject at its beginning) or function, both are pointers to one past
the last element of the same array object, or one is a pointer to one past
the end of one array object and the other is a pointer to the start of a
different array object that happens to immediately follow the first
array object in the address space.109)
109) Two objects may be adjacent in memory because they are adjacent
elements of a larger array or adjacent members of a structure with
no padding between them, or because the implementation chose
to place them so, even though they are unrelated.
If prior invalid pointer operations (such as accesses outside array bounds)
produced undefined behavior, subsequent comparisons also produce undefined
behavior.
===========================================================================
[...]
Post by Ðlе Ð
trеÑÑhеr3. Man kann Pointer in Integer konvertieren. Das Ergebnis ist
implementationsabhängig.
Das steht alles in 6.3.2.3 Pointers.
Ja, kenne ich, das Zitat stammt von mir.
Daher ist mir bekannt, daß die Implementationsabhängigkeit bedingt ist.
========================================================================
6.5.4 Cast operators
Preceding an expression by a parenthesized type name converts
the value of the expression to the named type.
This construction is called a cast.104)
A cast that specifies no conversion has no effect on the type
or value of an expression.
If the value of the expression is represented with greater range
or precision than required by the type named by the cast (6.3.1.8),
then the cast specifies a conversion even if the type of the expression
is the same as the named type and removes any extra range and precision.
========================================================================
Eine _mögliche_ Wertänderung durch einen Cast
wird im zweiten Absatz erklärt.
Weitere Gründe und Möglichkeiten für eine Wertänderung
sind nicht genannt.
Gäbe es sie, würden sie angegeben sein.
========================================================================
6.2.6.2 Integer types
The precision of an integer type is the number of bits it uses
to represent values, excluding any sign and padding bits.
========================================================================
Ein Cast 'Pointer zu Integer' wird nur einen Wert zum Integer
transportieren.
Post by Ðlе Ð
trеÑÑhеrDa steht *nichts* drin, was der "Wert" eines Pointers ist, und die
Details der KOnversion sind explizit "implementationsabhängig".
Es ist vielfältig und vielerorts erklärt, was der Wert eines Pointers ist.
Beispielsweise bei 'Relational operators'.
Implementationsabhängigkeit ist überhaupt kein Nachteil.
Wenn die Implementation eine optimale Definition trifft, so ist das gut!
Post by Ðlе Ð
trеÑÑhеrDem Implementierer steht es frei, bei der Konversion z.B. Prüfbits
hinzuzufügen, das ist vollkommen implementationsabhängig.
Ja, aber die dürfen dann nicht in Erscheinung treten.
Es geht in den Ausdrücken um Wert-Bits(+Sign-Bit).
Post by Ðlе Ð
trеÑÑhеrInteressanterweise ist nichtmal definiert, dass
(uintptr_t)(void *)0 == 0
gilt.
Ja, aber das ist egal.
R.Weikusat und ich prüfen, ob ein Pointer aus einem Array stammt.
Vergessen?
Post by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongPost by Ðlе Ð
trеÑÑhеrDarum kann man über den Größenvergleich von (uintptr_t)a und
(uintptr_t)b keine Aussagen machen, selbst wenn man weiß, dass a<b.
Du hast u.a. '6.3.2.3 Pointer' nicht vollständig gelesen
und/oder verstanden.
Gesamtheitliche Gedanken und diverse Ausschlüsse sind hier wichtig.
Dann leite doch mal (uintptr_t)a<(uintptr_t)b aus a<b mit dem Wortlaut
des Standards her.
Das habe ich mit diesem Posting mit all seinen Zitaten getan.
Suchst Du nun einen entsprechenden Satz in:
7.20.1.4 Integer types capable of holding object pointers
Post by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongMein Algorithmus und der von R.Weikusat prüfen, ob Adressenzahlen
innerhalb des Bereiches der Adressenzahlen eines Arrays liegen.
C kennt aber keine "Adresszahlen". C kennt Pointer. Und die kann man per
Cast in Zahlen konvertieren. Die Regeln (Größenrelationen) gelten aber
für die *Pointer*, nicht für die Zahlen.
Das mit den 'Adressenzahlen' ist kein Gegenargument.
R.Weikusat und ich prüfen, ob ein Pointer aus einem Array stammt.
R.Weikusat und ich prüfen, ob eine Adressenzahl innerhalb der
begrenzenden Adressenzahlen eines Arrays liegt.
Beides ist richtig.
'Relational operators' gelten u.a. für Pointer und Integer.
Das ist sogar ein Beweis, daß Pointer auch 'Zahlen' sind.
Post by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongEin Array hat vom Beginn bis hinter sein Ende garantiert gleichmäßig
aufsteigende Adressenzahlen ohne Lücken.
Das ist nicht spezifiziert. Es ist nur spezifiziert, dass man sie mit
aufsteigenden Pointern ansprechen kann. Die Repräsentation der Pointer
durch Zahlen ist nicht notwendig lückenlos oder aufsteigend.
Das ist allein mehrfach in den Zitaten dieses Postings spezifiziert.
Ein Array liegt im Speicher und hat Adressen.
Ein Array ist lückenlos mit seinen Elementen und hat aufsteigende
Adressen für jedes seiner Bytes und Elemente.
Diese Adressen können in Pointer-Variablen gespeichert werden.
Wenn diese Adressen mit (uintptr_t)(void*) versehen werden, dann
sind die resultierenden Zahlen garantiert aufeinanderfolgend
und mit festem Abstand, könnten aber absteigend sein.
Solch eine Formulierung steht nicht im Standard, nein, aber
sie _ergibt sich_ aus dem Standard.
Es ist ausgeschlossen, daß die resultierenden Zahlen in Reihenfolge
beispielsweise lauten: 10245 56 23977 172 1891 ...
Sie sind streng monoton steigend oder fallend, mit
einem festen Abstand, bei Elementen eines Arrays als Quelle.
Post by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongWenn eine Adressenzahl aus dem jeweiligen Array stammt, kann das auch
zweifelsfrei festgestellt werden.
Es gibt keine "Adressen" in C. Es gibt Pointer.
==========================================================================
6.2.8 Alignment of objects
Complete object types have alignment requirements which place
restrictions on the addresses at which objects of that type
may be allocated.
An alignment is an implementation-defined integer value representing the
number of bytes between successive addresses at which a given object
can be allocated.
==========================================================================
Es gibt eben doch Adressen in C.
Nicht nur vorstehend erwähnt.
Ich erkenne auch einen Unterschied zwischen Adressen und Pointern.
Post by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongJeder beliebige Pointer kann in einen Integer verwandelt werden.
Aber aufeinanderfolgende Pointer müssen nicht notwendig in
aufeinanderfolgende Integer umgewandelt werden. Das ist
implementationsabhängig.
Doch. Siehe oben.
Post by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongPost by Ðlе Ð
trеÑÑhеrPost by Helmut SchellongPost by Ðlе Ð
trеÑÑhеres gilt nicht mal notwendigerweise, dass
(uintptr_t)a + 1 == (uintptr_t)(a + 1)
Vorstehendes ist selbstverständlich.
Und folgt aus welchem Teil des Standards?
Ist Dir das unbekannt?
Z.B. 6.5.6 Additive operators
Abschnitt 8 dort betrifft die Addition von ints zu einem Pointer, und
der sagt nichts über die anschließende Umwandlung des Pointers in
Integers aus.
Homomorpfieerhalt bei der Umwandlung von Pointern in Integers ist
einfach nicht im Standard festgelegt.
Hää?!
{(uintptr_t)a} + {1} == (uintptr_t){(a + 1)}
Es geht hier darum, daß erstens eine Zahl zu einer Zahl
addiert wird, und zweitens die gleiche Zahl zu einem Pointer
addiert wird!
D a s ist hier der Unterschied!
--
Mit freundlichen Grüßen
Helmut Schellong ***@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm