Bit Flags

von christian | 2 | 13977 Aufrufe

Anzeige Hier werben

Mit Hilfe von bit flags kann man mehrere Zustände in einer einzigen Zahl unterbringen. Dies ist z.B. bei Rückgabewerten von Funktionen nützlich. In diesem Tutorial zeige ich die Verwendung von Bit-Flags anhand einer einfachen Formular-Überprüfung mit PHP.

Zunächst definieren wir einige Konstanten welche die einzelnen Flags repräsentieren. Diese verbessern später die Lesbarkeit des Codes. Sind aber nicht zwingend erforderlich.

 
PHP
1
2
3
4
5
6
define('_NO_USERNAME',      1);
define('_NO_PASSWORD',      2);
define('_NO_EMAIL',         4);
define('_INVALID_USERNAME', 8);
define('_INVALID_PASSWORD', 16);
define('_INVALID_EMAIL',    32);

Um zu verstehen was Bit-Flags eigentlich sind, schreiben wir das ganze in binärer Form.

 
PHP
1
2
3
4
5
6
define('_NO_USERNAME',      bindec(000001));
define('_NO_PASSWORD',      bindec(000010));
define('_NO_EMAIL',         bindec(000100));
define('_INVALID_USERNAME', bindec(001000));
define('_INVALID_PASSWORD', bindec(010000));
define('_INVALID_EMAIL',    bindec(100000));

Flag setzen

Nun initialisiert man zunächst die Fehlercode-Variable ($failure_code) mit 0. Möchte man ein bestimmtes Flag setzen bedient man sich einer sogenannten Bitmaske. Die Bitmaske entspricht dem zu setzenden Bit. Bitmaske und Wert verknüpft man mit einem bitweisen OR (|). Die beiden Werte werden dadurch bit für bit mit einem OR verknüpft. Im folgenden Beispiel wird das _NO_PASSWORD-bit gesetzt. Die entsprechende Bitmaske wäre also 000010 (Dezimal: 2)

 
Text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
   000000 Wert
OR 000010 Bitmaske
_________
   000010

Einen weiteres Flag setzen:

   000010 Wert
OR 010000 Bitmaske
_________
   010010

In PHP sieht dies wie folgt aus:

 
PHP
1
2
3
$failure_code = 0;

$failure_code |= _NO_PASSWORD;

Flag auslesen

Hier kommt wieder die Bitmaske ins Spiel. Diese verknüpft man diesmal aber mit einem bitweisen AND (&) mit dem Wert. Die beiden binären zahlen werden dadurch bit für bit mit einem AND verknüpft. Ergebnis dieser Operation ist entweder 1 (true) oder 0 (false). Im folgenden Beispiel wird überprüft ob das _NO_EMAIL-Bit gesetzt ist. Die entsprechende Bitmaske wäre also 000100 (Dezimal: 4).

 
Text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Fall 1: Bit/Flag ist gesetzt.

    000100 Wert
AND 000100 Bitmaske
__________
    000100 True

Fall 2: Bit/Flag ist nicht gesetzt.

    000000 Wert
AND 000100 Bitmaske
__________
    000000 False

In PHP sieht das ganze wie folgt aus:

 
PHP
1
2
3
4
5
6
$failure_code = 0;

if($failure_code &_NO_EMAIL)
    echo 'Flag/Bit ist gesetzt.';
else
    echo 'Flag/Bit ist nicht gesetzt.';

Beispiel

Nun ein praktisches Beispiel:

 
PHP
 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?php

define('_NO_USERNAME',      1);
define('_NO_PASSWORD',      2);
define('_NO_EMAIL',         4);
define('_INVALID_USERNAME', 8);
define('_INVALID_PASSWORD', 16);
define('_INVALID_EMAIL',    32);

function validate($username,$password,$email)
{
    $failure_code = 0;
    if($username == '')
        $failure_code |= _NO_USERNAME;

    if($password == '')
        $failure_code |= _NO_PASSWORD;

    if($email == '')
        $failure_code |= _NO_EMAIL;

    if(!preg_match('~^[a-zA-z0-9].*~',$username))
        $failure_code |= _INVALID_USERNAME;

    $strlen = strlen($password);
    if($strlen<20 && $strlen>4)
        $failure_code |= _INVALID_PASSWORD;

    if(!preg_match('~^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([0-9]{1,3})|([a-zA-Z]{2,3})|(aero|coop|info|museum|name))$~',$email))
        $failure_code |= _INVALID_EMAIL;

    return $failure_code;
}

if($_GET['action']=='validate')
{
    $failure_code = validate($_POST['username'],$_POST['password'],$_POST['email']);
    
    if($failure_code==0)
        echo 'Alles korrekt.';
    else
    {
        if($failure_code &_NO_USERNAME)
            echo 'Username fehlt.';
    
        if($failure_code &_NO_EMAIL)
            echo 'E-Mail fehlt.';

        if($failure_code &_NO_PASSWORD)
            echo 'Passwort fehlt.';
    
        if($failure_code &_INVALID_USERNAME)
            echo 'Username ungültig.';
    
        if($failure_code &_INVALID_EMAIL)
            echo 'E-Mail ungültig.';

        if($failure_code &_INVALID_PASSWORD)
            echo 'Passwort ungültig.';
    }
?>

<form action="?action=validate" method="post">
Username<br/>
<input type="text" name="username" /><br/>
Passwort<br/>
<input type="password" name="password" /><br/>
E-Mail<br/>
<input type="text" name="email" /><br/>
</form>
Über den Autor: christian
hat keine Beschreibung angegeben. Eine Beschreibung kann man unter dem Punkt "Profil bearbeiten" im Kontrollzentrum eintragen.
Profilseite betrachten