Был бы потерян знак: обнуление младших битов - PullRequest
0 голосов
/ 10 июля 2020

У меня есть класс Coord вроде этого:

class Coord
{
public:
    Coord(int32_t x, int32_t y, int32_t z): mVec{{x, y, z}} {}
    
    int32_t operator[](size_t i) const { assert(i < 3); return mVec[i]; }

private:
    std::array<int32_t, 3> mVec
}

Теперь я использую свой класс:

Coord origin(-1, 2, -4);

uint32_t DIM = 1 << 12; // 2 ^ 12

// zero out the low-order bits
Coord originAfter = Coord(origin[0] & ~(DIM - 1),
                          origin[1] & ~(DIM - 1),
                          origin[2] & ~(DIM - 1));

Не теряет ли originAfter знак origin?

ОБНОВЛЕНИЕ

Код доступен здесь .

1 Ответ

2 голосов
/ 10 июля 2020

В шестнадцатеричном формате DIM равно 00001000, DIM-1 равно 00000FFF, а ~(DIM-1) равно FFFFF000. Затем операция & сохраняет все биты, которые установлены в ~(DIM-1), и обнуляет все биты, которые очищены в ~(DIM-1). Таким образом, младшие 12 бит обнуляются, а старшие 20 бит сохраняются. Поскольку знаковый бит является старшим битом, он сохраняется.

Технически, однако, это неопределенное поведение при использовании с отрицательным числом. В этом случае результатом origin[0] & ~(DIM - 1) будет большое количество без знака, которое переполняется при назначении mVec[0], которое является количеством со знаком. Однако в реальном мире это не проблема.

...