Skip to content

Instantly share code, notes, and snippets.

@hidsh

hidsh/mod.c Secret

Created January 3, 2023 07:24
Show Gist options
  • Select an option

  • Save hidsh/b1d6793ac4b0165d95e6e6e30326a16a to your computer and use it in GitHub Desktop.

Select an option

Save hidsh/b1d6793ac4b0165d95e6e6e30326a16a to your computer and use it in GitHub Desktop.
C言語のmod演算 (e.g. X % 4) の動作を確認する。主に第1項が負の値のとき。
#include <stdio.h>
#include <stdint.h> // uint8_t
/*
何を見る?:
テーブルやリングバッファの位置を指す変数が増加方向にも減少方向にも辿れるように、C言語の演算 X % 4 の動作を確認する
結果:
X % 4 は Xが正の値のときは期待通りに動くが、Xが負の値のときは期待通りには行かない
なので、Xが正/負のどちらの値でも同一の式でやるには以下のようにする
(4 + X) % 4
*/
int main(void)
{
const uint8_t STATE_TBL[] = { 0b00, 0b01, 0b11, 0b10 };
const uint8_t N_STATE_TBL = sizeof(STATE_TBL) / sizeof(STATE_TBL[0]);
printf("N_STATE_TBL: %d\n", N_STATE_TBL);
int8_t idx = 0;
// 正の値を4で割った余りを出す
for (int i=0; i<8; i++) {
printf("idx %d\n", idx);
// idx = (idx + 1) % N_STATE_TBL; // 第1項が正の値だけならこれでいい
idx = (N_STATE_TBL + (idx + 1)) % N_STATE_TBL; // 第1項が負の値のときと同じ式で、正の値でも問題ないことを確認
}
printf("------\n");
idx = 0;
// 負の値を4で割った余りを出す
for (int i=0; i<8; i++) {
printf("idx %d\n", idx);
idx = (N_STATE_TBL + (idx - 1)) % N_STATE_TBL; // 第1項が負の値のときの式はこうする
// idx = (idx - 1) % N_STATE_TBL + N_STATE_TBL; // ここ→によるとこれでいいはずらしいけどダメだった https://daeudaeu.com/mod-sign/
}
return 0;
}
/*
❯❯❯ gcc mod.c && ./a.out
N_STATE_TBL: 4
idx 0
idx 1
idx 2
idx 3
idx 0
idx 1
idx 2
idx 3
------
idx 0
idx 3
idx 2
idx 1
idx 0
idx 3
idx 2
idx 1
*/
@hidsh

hidsh commented Jan 3, 2023

Copy link
Copy Markdown
Author

うまく行かない例

正の値のときの式 idx = (idx - 1) % N_STATE_TBL; のままで負の値の演算をすると、
演算結果がマイナスになるのでこのままでは配列の添字に使えない。

❯❯❯ gcc mod.c && ./a.out
N_STATE_TBL: 4
idx 0
idx 1
idx 2
idx 3
idx 0
idx 1
idx 2
idx 3
------
idx 0            <-- これは期待どおり
idx -1           <-- これな。期待値は3
idx -2           <-- これな。期待値は2
idx -3           <-- これな。期待値は1
idx 0                  以下略
idx -1
idx -2
idx -3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment