PHP, karakter işleme C

4 Cevap php

Ben herhangi bir şekilde değiştirmek için izin veya değiştirin değilim (bir makro gibi) bazı eski C kodu var.

Bu kod (sonunda) dize her karakter için karma değer bir işlem gerçekleştirilirken, kaynak dize dayalı bir özet (C) dize dışarı çıktılar.

#define DO_HASH(src, dest) { \
    unsigned long hash = 1111; // Seed. You must NOT change this. \
    char c, *srcPtr; \
    int i; \
    unsigned char hashedChar; \
    \
    srcPtr = src; \
    c = *srcPtr++; \
    while ( c) { \
            hash = ((hash << 5) + hash) + c; \
            c = *srcPtr++; \
    } \
    ... // etc.

} // 

Birkaç yıl önce, ben bir özet dize döndüren bir fonksiyonu olarak, PHP bunu uygulamak zorunda. PHP işlevi aynı C sonuçları yeniden zorundadır.

function php_DO_HASH($srcStr)
{
    $hash = 1111;       // Seed. You must NOT change this.
    $index = 0;
    $c = $srcStr[$index];

    while ($c) {
        $hash = (($hash << 5) + $hash) + ord($c);
        $index++;
        $c = $srcStr[$index];
    }

    ... // etc.
}

Bu, bazı yıldır başarıyla çalıştı. Ancak, son birkaç gün içinde benim sunucu host CentOS yeni bir sürüme yükseltilmiş, ancak PHP sürümü değişmedi diyor. O zamandan beri, iki kodları şimdi farklı bir çıktı oluşturmak.

Herkes PHP sürümü yanlış yapıyorum ne kadar tavsiye eder misiniz? Teşekkürler.

4 Cevap

Sen this question olarak (davranış sürümleri arasında değişir) aynı PHP taşma sorunu haline yayınlanıyor. Görünüşe PHP'nin tüm sürümlerinde çalışan bu kesiği-to-32-bit fonksiyonu dahil olmak üzere tüm kanlı detayları, var olan kabul edilen yanıt:

function thirtyTwoBitIntval($value)
{
    if ($value < -2147483648)
    {
        return -(-($value) & 0xffffffff);
    }
    elseif ($value > 2147483647)
    {
        return ($value & 0xffffffff);
    }
    return $value;
}

Bunu aracılığıyla hash değeri geçerse thirtyTwoBitIntval() yeniden hesaplanmalıdır her zaman işlev, yani:

hash = thirtyTwoBitIntval(($hash << 5) + $hash + ord($c));

o sorunu düzeltmek gerekir.

Belki de bir 64-bit sistem değişti? Her turdan sonra 0xffffffff ile hash değerini bitanding denemelisiniz.

The while-conditions of your C and PHP version differ.
The C version aborts when there is '\0' character (ord('\0')===0, zero-terminated string) while the php version doesn't. On the other hand the php version will stop at a '0' character (ord('0')===48) while the c version doesn't.

edit: Orada might da değer aralıkları ve türü dönüştürme ile ilgili bir sorun olabilir. Php hiçbir unsigned uzunluğunda bir türü vardır. Ek sonucu PHP_INT_MAX'tan daha büyük Ama php bir şamandıraya bir tamsayı dönüştürür. örneğin

var_dump(PHP_INT_MAX);
var_dump(PHP_INT_MAX + 1);

baskılar (Benim 32bit makinede)

int(2147483647)
float(2147483648)

I-think Bir sonraki << "Düzeltmeler" bu sorunu (php sizin algoritması ile "çalışan" bir şekilde bir geri int şamandıra dönüştürür beri). Ama döngü sonra $ hash ile ne yaptığınızı bağlı olarak bu bir sorun olabilir.

Bu varsayılan uygulamanız için değişip değişmediğini PHP hakkında çok şey bilmiyorum, ama indekslerin 0 veya 1 başlar seçebilirsiniz hatırlıyorum. Bu kontrol etmek faydalı olabilir, ve.

Ama, ne istediğinizi bu zorlamak için ayarlamak için bir değişken olduğuna inanıyorum.


Eğer döngü sonlandırmak için dizenin sonunda boş karakter hala var emin misin Ayrıca, while $c C çok anlamıyla tercüme olarak görünüyor?