Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Bitoperations

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
02.03.2009, 14:25 Uhr
mike
Pinguinhüpfer
(Operator)


Hi

Weiß jemand wie man ellegant die 5 höchstwertigsten Bits ausschalten kann? Hab jetzt
value <<= 5; value >>=5;

Gibts da was "schöeneres"?

Danke
lg

EDIT: Achja. Erlaubt ist nur C - also kein bitset oder so
--

Dieser Post wurde am 02.03.2009 um 14:27 Uhr von mike editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
02.03.2009, 15:19 Uhr
TOSHMAX



Hallo,

ich weiß nicht genau ob es das ist was du brauchst, aber hier mal meine Lösung:

C++:
value &= (1 << 3) - 1;



'value' würde jetzt nur die ersten 3 Bits speichern, also die 5 höchsten rauswerfen.
Vielleicht hilft es dir ja.

Gruß
TOSHMAX
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
02.03.2009, 15:44 Uhr
Hans
Library Walker
(Operator)


value &= (~0)>>5;

wobei ich mir jetzt nicht sicher bin, wie das in diesem Fall mit dem Shiftoperator gehandhabt wird, d.h. ob ein arithmetischer Shift oder ein logischer Shift eingesetzt wird. Im Fall eines arithmetischen Shifts werden nämlich Einsen eingeschoben, im logischen Fall Nullen. Ich glaube das hängt vom Datentyp von value ab; - ist value ein signed type setzt der Compiler arithmetische Shifts, im Fall von unsigned logische. Aber das solltest Du austesten bevor Du es benutzt.


Bearbeitung:

Habs jetzt mal ausprobiert, das Ergebnis gibt zu denken...

C++:
#include <stdio.h>

int main()
{
  int value1;
  unsigned value2;

  value1 = -1;
  printf ("\nvalue1: %0x, ", value1);
  value1 &= (~0)>>5;
  printf ("nach Bitop: %0x\n", value1);

  value2 = ~0;
  printf ("\nvalue2: %0x, ", value2);
  value2 &= (~0)>>5;
  printf ("nach Bitop: %0x\n", value2);

  return 0;
}


liefert:

Code:
value1: ffffffff, nach Bitop: ffffffff
value2: ffffffff, nach Bitop: ffffffff




--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.

Dieser Post wurde am 02.03.2009 um 16:40 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
02.03.2009, 16:23 Uhr
ao

(Operator)



Zitat von mike:
Hi

Weiß jemand wie man ellegant die 5 höchstwertigsten Bits ausschalten kann? Hab jetzt
value <<= 5; value >>=5;


Vorsicht, das klappt so nur bei unsigned-Typen!

Bei signed-Typen werden beim Rechtsschieben von links Einsen aufgefüllt, falls nach dem Linksschieben das vorderste Bit eine 1 ist.

Was ist die Anwendung? Immer genau 5 Bits ausschalten? Und immer auf 32-Bit-Typen? Oder ist irgendwas davon variabel?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
02.03.2009, 17:08 Uhr
mike
Pinguinhüpfer
(Operator)


Danke für die zahlreichen Antworten.
Regelfall ist 32bit unsigned long. 5 bits ist allerdings variabel
--
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
02.03.2009, 17:18 Uhr
0xdeadbeef
Gott
(Operator)



C++:
template<typename t> disable_top_bits(t x, int num) {
  return x & (t(1) << sizeof(t) * 8 - num) - 1;
}


sollte für alle Integer-Sorten funktionieren.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 02.03.2009 um 17:25 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
02.03.2009, 20:33 Uhr
Hans
Library Walker
(Operator)


@Beefy:

Zitat von mike:
EDIT: Achja. Erlaubt ist nur C - also kein bitset oder so


Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
02.03.2009, 22:01 Uhr
mike
Pinguinhüpfer
(Operator)


Aber trotzdem coole Lösung

Ich bin auch doof. & ist eh klar. Hab mir alle Operatoren durchgedacht und hatte da einen kapitalen Denkfehler hrrrrr

Danke für alle Antworten

lg
--
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
02.03.2009, 22:19 Uhr
0xdeadbeef
Gott
(Operator)


Naja, in C wirste das für jeden Typen überladen oder ein Makro schreiben müssen. Wenn du den Typ eh von Hand verwalten musst, ist es im Zweifel wohl auch sinnvoller, (unsigned typ) -1 >> num als Maske zu benutzen, um die Subtraktion zu sparen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
05.03.2009, 23:15 Uhr
Hans
Library Walker
(Operator)


Hi,

hab noch einen Nachtrag zu posting 002:

Habe mal einen Blick auf den Assemblercode geworfen, den mein Compiler produziert hat, das fand ich sehr verwunderlich... hier mal die wesentlichen Auszüge:


Code:
;   int value1;
;   unsigned value2;
;
;   value1 = -1;
L$1:
    mov         dword ptr [ebp-8],0ffffffffH

;   printf ("\nvalue1: %0x, ", value1);
    mov         eax,dword ptr [ebp-8]
    push        eax
    mov         eax,offset FLAT:L$4
    push        eax
    call        near ptr FLAT:printf_
    add         esp,8

;   value1 &= (~0)>>5;
;   printf ("nach Bitop: %0x\n", value1);
    mov         eax,dword ptr [ebp-8] ; <- eine konstante?!
    push        eax
    mov         eax,offset FLAT:L$5
    push        eax
    call        near ptr FLAT:printf_
    add         esp,8

;
;   value2 = ~0;
    mov         dword ptr [ebp-4],0ffffffffH

;   printf ("\nvalue2: %0x, ", value2);
    mov         eax,dword ptr [ebp-4]
    push        eax
    mov         eax,offset FLAT:L$6
    push        eax
    call        near ptr FLAT:printf_
    add         esp,8

;   value2 &= (~0)>>5;
;   printf ("nach Bitop: %0x\n", value2);
    mov         eax,dword ptr [ebp-4] ; <- eine konstante?!
    push        eax
    mov         eax,offset FLAT:L$5
    push        eax
    call        near ptr FLAT:printf_
    add         esp,8


Demnach hat der Compiler die Bitschiebeoperation schon selber ausgewertet, und daraus einen konstanten Wert gemacht. Da der Zweck des Programms aber darin bestand, herauszufinden, in welchen Befehlen die Bitschiebeoperationen münden, ist festzustellen, das es seinen Zweck nicht erfüllt hat.

Um dem Compiler das vorherige auswerten abzugewöhnen hab ich den Wert 5, um den die Bits zu verschieben sind, durch eine Variable ersetzt, die der Benutzer eingeben muss. Also so:
C++:
int value1, s1;
  unsigned value2, s2;

  value1 = -1;
  printf ("\nvalue1: %0x, ", value1);
  printf ("\nAnzahl verschiebungen: ");
  scanf ("%d", &s1);
  value1 &= (~0)>>s1;
  printf ("nach Bitop: %0x\n", value1);

  value2 = ~0;
  printf ("\nvalue2: %0x, ", value2);
  printf ("\nAnzahl verschiebungen: ");
  scanf ("%d", &s2);
  value2 &= (~0)>>s2;
  printf ("nach Bitop: %0x\n", value2);


Daraus wurde dann:

Code:
...
  value1 &= (~0)>>s1;
0051    8A 4D F4                  mov         cl,byte ptr [ebp-0xc]
0054    B8 FF FF FF FF            mov         eax,0xffffffff
0059    D3 F8                     sar         eax,cl ; Shift arithmetic right
005B    21 45 F0                  and         dword ptr [ebp-0x10],eax
...
  value2 &= (~0)>>s2;
00A9    8A 4D FC                  mov         cl,byte ptr [ebp-0x4]
00AC    B8 FF FF FF FF            mov         eax,0xffffffff
00B1    D3 F8                     sar         eax,cl ; ebenfalls Shift arithmetic right
;                                                     erwartet hab ich hier: SHR, also
;                                                     Shift right
00B3    21 45 F8                  and         dword ptr [ebp-0x8],eax



Daraus schliesse ich: Wenn es darum geht, das die oberen Bits wirklich gelöscht werden sollen, wäre eine fertige Bitmaske die bessere Lösung. Etwa so:

C++:
unsigned int masken[] = {0x8000, 0x4000, 0x2000, 0x1000,
                         0x0800, 0x0400, 0x0200, 0x0100,
                         0x0080, 0x0040, 0x0020, 0x0010,
                         0x0008, 0x0004, 0x0002, 0x0001};
...
/* obere 5 Bit löschen */
value &= ~(masken[0] | masken[1] | masken[2] | masken[3] | masken[4]);



Ach ja, dann noch das hier:

Zitat von 0xdeadbeef:

in C wirste das für jeden Typen überladen ... müssen.


Wie stellt man das an?

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.

Dieser Post wurde am 05.03.2009 um 23:23 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: