оператор >> и << вывод обнуляется при выводе - PullRequest
0 голосов
/ 27 мая 2011

Я не понимаю, почему выходные данные обеих функций обнуляются при выводе их:

class uint128_t{

private:
    uint64_t UPPER, LOWER;

public:
    // constructors
    uint128_t(){
        UPPER = 0;
        LOWER = 0;
    }

    template <typename T>
    uint128_t(T rhs){
        UPPER = 0;
        LOWER = (uint64_t) rhs;
    }

    template <typename S, typename T>
    uint128_t(const S upper_rhs, const T lower_rhs){
        UPPER = (uint64_t) upper_rhs;
        LOWER = (uint64_t) lower_rhs;
    }

    uint128_t(const uint128_t & rhs){
        UPPER = rhs.UPPER;
        LOWER = rhs.LOWER;
    }

    //  RHS input args only

    // assignment operator
    template <typename T> uint128_t & operator=(T rhs){
        UPPER = 0;
        LOWER = (uint64_t) rhs;
        return *this;
    }

    uint128_t & operator=(uint128_t & rhs){
        UPPER = rhs.UPPER;
        LOWER = rhs.LOWER;
        return *this;
    }


    uint128_t operator<<(int shift){
        if (shift >= 128)
            return uint128_t(0, 0);
        else if (shift == 64)
            return uint128_t(LOWER, 0);
        else if (shift < 64)
            return uint128_t((UPPER << shift) + (LOWER >> (64 - shift)), LOWER << shift);
        else if ((128 > shift) && (shift > 64)){
            uint128_t a =uint128_t(LOWER << (shift - 64), 0);
            // a will show the correct values 
            std::cout << a.upper() << " " << a.lower() << std::endl;
            return uint128_t(LOWER << (shift - 64), 0);
            // in the program that includes this, printing out the values show 0 0
        }
    }

    uint128_t operator>>(int shift){
        if (shift >= 128)
            return uint128_t(0, 0);
        else if (shift == 64)
            return uint128_t(0, UPPER);
        else if (shift <= 64)
            return uint128_t(UPPER >> shift , ((UPPER << (64 - shift))) + (LOWER >> shift));
        else if ((128 > shift) && (shift > 64))
            return uint128_t(0, (UPPER >> (shift - 64)));
    }

    uint128_t operator<<=(int shift){
        *this = *this << shift;
        return *this;
    }

    uint128_t operator>>=(int shift){
        *this = *this >> shift;
        return *this;
    }

    const uint64_t upper() const {
        return UPPER;
    }

    const uint64_t lower() const {
        return LOWER;
    }

// lots of other stuff

};

int main(){

    uint128_t a(0x123456789abcdef1ULL, 0x123456789abcdef1ULL);

    a>>= 127; // or a <<= 127;
    std::cout <<a.upper() << " " <<a.lower() << std::endl;
    return 0;
}

http://ideone.com/jnZI9

Кто-нибудь может понять, почему?

Ответы [ 3 ]

3 голосов
/ 27 мая 2011

Ваше int - 128 бит, вы сдвигаете его вниз (вправо) на 127 бит, что означает, что самый старший бит будет перемещен в самую нижнюю позицию, а все остальные биты будут равны 0.

Но int в вашем примере - 0x1...., 0x1 (самый высокий клев) - 0001 в двоичном формате, для которого не установлен верхний бит. Так что 0 - правильный вывод.

Если вы измените 0x1... на 0x8... (или что-то большее, чем 0x7), вы, скорее всего, увидите 0 ... 1 в выводе.

2 голосов
/ 27 мая 2011

>> 127 означает сдвиг крайних правых 127 бит в числе. Поскольку ваш uint128_t равен 0x1234 ...., самый значимый бит - это «0». После a >>= 127 число становится равным 0, поэтому на выходе получается 0 0, как и ожидалось.


Что касается <<=, это потому, что

uint128_t & operator=(uint128_t & rhs)

не соответствует значению rhs, а

template <typename T> uint128_t & operator=(T rhs)

соответствует, когда T == uint128_t также, поэтому в

    *this = *this << shift;

будет выбран оператор присваивания шаблона, который назначает только нижний uint64_t. Вы должны изменить подпись первого правопреемника оператора на

uint128_t& operator=(const uint128_t& rhs)
//                   ^^^^^
0 голосов
/ 27 мая 2011

Причина в следующем:

Тип UPPER является 64-разрядным целым числом. Кроме того, вы пытаетесь сместить целое число на 63 бита, а в вашем случае 64-й бит равен нулю. Таким образом, вы теряете все 63 бита, которые на самом деле содержат число.

PS: Вы сказали, что вам не нравится использовать отладчик, но если бы вы только использовали его, это было бы действительно очень легко понять самостоятельно.

...