Namaran

Code daily. Without assist.

2026-09-19

ring_buffer.cpp

#include <array>
#include <cstdio>

int prev_index(int index, int size) {
    return (index - 1) % size;
}

int main() {
    std::array<int, 4> buffer = {10, 20, 30, 40};
    int idx = prev_index(0, static_cast<int>(buffer.size()));
    std::printf("%d\n", buffer[idx]);
}

prev_index(0, 4)は末尾の要素(buffer[3]、値40)を指すつもりですが、実際にはそうなりません。何が問題で、どう直せばよいでしょうか?

Answer

%は被除数の符号を引き継ぐので、index0のとき(index - 1) % size-1 % 4、つまり-1になります(43ではありません)。これをbuffer[idx]の添字に使うと、負のインデックスで配列の外を読む未定義動作になります。「一周させたいなら%を書けばよい」という発想は、Pythonのように剰余が常に非負になる言語では通用しますが、C++の%は0方向への切り捨てに合わせた符号を返すので、そのままでは負の値が出てきてしまいます。一周分のsizeを先に足してから%を取れば、引き算の結果がどんな値でも非負の範囲に収まります:

int prev_index(int index, int size) {
    return (index - 1 + size) % size;
}