Der Martin: Bitweiser Zugriff

Beitrag lesen

Moin Daniel,

int bitreadshift(int i, int j) {
  return (i & (1 << j)) != 0;
}

wie ich schon Peter gegenüber angedeutet habe, geht es in den meisten Fällen, wo einzelne Bits abgefragt werden, nicht um die tatsächliche Wertigkeit des jeweiligen Bits; daher ist hier der Vergleich !=0 eigentlich sinnfrei (schadet aber auch nicht). Das Funktionsergebnis wird ja im realen Kontext sowieso auf "ungleich Null" abgefragt.

int bitreadarray(int i, int j) {
  return (i & array[j]) != 0;
}

Dito.

Vergessen:

long int time1 = clock() / (CLOCKS_PER_SEC / 1000.0);

for (int j = 0; j < count; ++j) {
    /* int k = 1 + (int) (31.0 * (rand() / (RAND_MAX + 1.0))); */
    for (int k = 0; k < 32; ++k) {
      x += bitreadshift(i, k);

Okay, hier kommt der numerische Wert doch zum Tragen, das ist aber eine untypische Anwendung für eine Bit-Abfrage.

Für die misstrauischen habe ich das auch mal disassembliert:

Und dann noch in einer so merkwürdigen Notation.  :-|

080483e0 <bitreadshift>:
80483e0:       55                      push   %ebp
80483e1:       89 e5                   mov    %esp,%ebp
80483e3:       8b 45 08                mov    0x8(%ebp),%eax
80483e6:       8b 4d 0c                mov    0xc(%ebp),%ecx
80483e9:       5d                      pop    %ebp
80483ea:       d3 f8                   sar    %cl,%eax
80483ec:       83 e0 01                and    $0x1,%eax
80483ef:       c3                      ret

Hier erkennt man aber, dass der Compiler den Ausdruck umformuliert hat. Was hier in Assembler wirklich formuliert wird, ist  "return ((i>>j) & 1)". Ich finde das bemerkenswert.

080483f0 <bitreadarray>:
80483f0:       55                      push   %ebp
80483f1:       89 e5                   mov    %esp,%ebp
80483f3:       8b 45 0c                mov    0xc(%ebp),%eax
80483f6:       8b 55 08                mov    0x8(%ebp),%edx
80483f9:       5d                      pop    %ebp
80483fa:       85 14 85 a0 97 04 08    test   %edx,0x80497a0(,%eax,4)
8048401:       0f 95 c0                setne  %al
8048404:       0f b6 c0                movzbl %al,%eax
8048407:       c3                      ret

Auffällig finde ich, dass da bei der Array-Variante anscheinend die AND-Operation wegoptimiert wird.

Keineswegs. Die test-Anweisung ist nämlich ein AND, bei dem das Ergebnis nicht gespeichert wird, gerade für solche Bit-Tests gedacht.

So long,
 Martin

--
Das einzige Problem beim Nichtstun: Man weiß nie, wann man damit fertig ist.