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