Thread Archive-Flag (Win32::File): Archive-Flag löschen (26 answers)
Opened by weismat at 2003-08-27 00:31

Dubu
 2003-09-12 01:44
#80639 #80639
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
[quote=Crian,11.09.2003, 13:05]Ist denn bei Perl festgelegt, wie die Komplemente gebildet werden (auf wieviele binäre Stellen)?[/quote]
Ja und nein. ;-)
[quote=Symbolic Unary Operators,perlop]
Unary "~" performs bitwise negation, i.e., 1's complement. [...] Note that the width of the result is platform-dependent: ~0 is 32 bits wide on a 32-bit platform, but 64 bits wide on a 64-bit platform, so if you are expecting a certain bit width, remember use the & operator to mask off the excess bits.
[/quote]
Das sollte man auch im Hinterkopf behalten, wenn man damit rechnet, denn ob Perl eine Zahl als Integer oder Double speichert, kann man ihr von aussen ja nicht ansehen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ perl -V
Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
[...]
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8,
[...]

$ perl -le 'print ~0'     # Integer, 32-Bit-Plattform
4294967295

$ perl -le '$i=1_000_000_000; print ~~$i'    # doppelt negiert => gleicher Wert wie vorher
1000000000

$ perl -le '$i=8_000_000_000; print ~~$i'     # Zu gross fuer einen Int!
4294967295     # Ups!

Das letzte Ergebnis ist dann doch ueberraschend, denn es sieht so aus, als ob vorher eine 0 in $i gestanden haette, was aber nicht der Fall war.

Was da intern passiert kann man sich ungefaehr mit Devel::Peek anschauen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ perl -MDevel::Peek -le '$i=8_000_000_000; print Dump($i); \
     print ~~$i; print Dump($i)'

SV = NV(0x8175f88) at 0x8170fe8
 REFCNT = 1
 FLAGS = (NOK,pNOK)
 NV = 8000000000

4294967295
SV = PVNV(0x818d040) at 0x8170fe8
 REFCNT = 1
 FLAGS = (NOK,pIOK,pNOK,IsUV)
 UV = 4294967295
 NV = 8000000000
 PV = 0

Man sieht: Waehrend direkt nach der Zuweisung unsere skalare Variable (SV) $i intern als Double Float (NV) aufgefuehrt wird - klar, es ist zu lang fuer einen Integerwert - haben wir nach der print-Anweisung auf einmal neben dem Double noch einen unsigned Int (UV) und einen Stringwert (PV) fuer $i, obwohl die Variable selber nicht veraendert wurde. Ich kenne mich mit den Perl-Interna nicht genug aus, um das korrekt zu interpretieren, aber ich nehme an, dass Perl das bitweise Inverse nicht aus einem NV berechnen kann, sondern nur aus einem IV oder UV. Woher der PV dabei kommt, ist mir aber schleierhaft. Die Flags sagen interessanterweise aus, dass der NV weiterhin gueltig ist, aber intern (privat) noch ein Int, der unsigned ist, wenn ich das richtig interpretiere (pIOK, IsUV). Der auf einmal gefuellte Stringwert (PV) taucht in den Flags aber nicht auf.

Ebenfalls lustig wird es, wenn man sich anschaut, wie die Ergebnisse von ~$i und ~~$i an andere Variablen zugewiesen werden:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ perl -MDevel::Peek -le '$i=8_000_000_000; print Dump($i); \
   $j= ~$i; print Dump($i), Dump($j); \
   $k = ~~$i; print Dump($i), Dump($k)'

SV = NV(0x8175fe8) at 0x8171048
 REFCNT = 1
 FLAGS = (NOK,pNOK)
 NV = 8000000000

SV = PVNV(0x818d050) at 0x8171048
 REFCNT = 1
 FLAGS = (NOK,pIOK,pNOK,IsUV)
 UV = 4294967295
 NV = 8000000000
 PV = 0
SV = IV(0x817308c) at 0x81710c0
 REFCNT = 1
 FLAGS = (IOK,pIOK)
 IV = 0

SV = PVNV(0x818d050) at 0x8171048
 REFCNT = 1
 FLAGS = (NOK,pIOK,pNOK,IsUV)
 UV = 4294967295
 NV = 8000000000
 PV = 0
SV = IV(0x8173098) at 0x8176c4c
 REFCNT = 1
 FLAGS = (IOK,pIOK,IsUV)
 UV = 4294967295

In $j ist also ein Int, in $k ein unsigned Int, das Inverse von $i offensichtlich 0 und dessen Inverses (wie dann zu erwarten) 0xFFFFFFFF.

Manchmal graut es mir vor dem, das Perl intern so treibt... ;)
Wer sich mit Perls Opcodes auskennt, kann ja mal das erste Beispiel mit perl -MO=Concise durchnudeln und etwas mehr dazu erzaehlen. :)

Ach ja: Ich halt's fuer einen Bug.

View full thread Archive-Flag (Win32::File): Archive-Flag löschen