在C程序中,我随机增加数组中的一些整数元素.未增加的值无论如何都会发生变化.为什么?



我有一个包含400个元素的整数数组。我用0初始化每个元素(甚至在之后检查它是否真的是0,因为我找不到这种行为的原因)。

然后,我选择10000个随机[1]索引,并将这些索引处的数组元素增加一。随机选择的指数中没有一个大于321(我确实检查了一下)。然而,在这10000个随机增加之后,索引为399或398的数组元素大于0。为什么?

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
#include <time.h>
#define NUM_INCREASES 10000
#define RESULTS_SIZE 400
#define ONES_IDX 2
#define TENS_IDX 1
#define HUNDREDS_IDX 0
int main(int argc, char * argv[]) {
    int decimalDigits[3];
    int results[RESULTS_SIZE] = {0};
    srand(time(NULL));
    for (int i=0; i<RESULTS_SIZE; i++) {
        if (results[i]>0) {
            printf("%05d %05d n", results[i], i);
        }
    }
    puts("---");
    for (int i=0; i<NUM_INCREASES; i++) {
        decimalDigits[0] = 0;
        decimalDigits[1] = 0;
        decimalDigits[2] = 0;
        for (int digitIncrease = 0; digitIncrease<3; digitIncrease++) {
            int digitIndex = rand()%(decimalDigits[ONES_IDX]>0 ? 2 : 3);
            if (digitIndex == TENS_IDX && decimalDigits[TENS_IDX] == 2) {
                digitIndex -= 1 + 2*(i%2);
            }
            decimalDigits[digitIndex]++;
        }
        if (decimalDigits[TENS_IDX] > 2 || decimalDigits[ONES_IDX] > 1) {
            fprintf(stderr, "error %dn", __LINE__);
        }
        int toIncrease = decimalDigits[HUNDREDS_IDX] * 100 + decimalDigits[TENS_IDX] * 10 + decimalDigits[ONES_IDX];
        if (toIncrease < 0 || toIncrease > 321) {
            fprintf(stderr, "error %dn", __LINE__);
        }
        results[toIncrease]++;
    }
    for (int i=0; i<RESULTS_SIZE; i++) {
        if (results[i]>0) {
            printf("%05d %05d n", results[i], i);
        }
    }
    return EXIT_SUCCESS;
}

GCC和clang都会发生这种情况。我在三台不同的机器上看到过。valgrind和gdb都没有向我报告任何问题。

样本输出为

---
00183 00020 
01763 00021 
03618 00111 
01263 00120 
01738 00201 
01068 00210 
00367 00300 
00183 00399 

这里的错误是什么?399不应该在输出的第二列中。

脚注:

[1] 随机索引是从数字0开始生成的。然后将该数字的一个随机小数位数增加3倍。但是,"一"位数最多增加1次。"十"位数最多增加2倍。

当我按如下方式运行代码时,这一行会导致负数组索引:

for (int digitIncrease = 0; digitIncrease<3; digitIncrease++) {
    int digitIndex = rand()%(decimalDigits[ONES_IDX]>0 ? 2 : 3);
    if (digitIndex == TENS_IDX && decimalDigits[TENS_IDX] == 2) {
        digitIndex -= 1 + 2*(i%2);
    }
    decimalDigits[digitIndex]++;  //Negative array index here
}

我至少会开始查看那个块,也就是说,它不容易遵循,可能是你逻辑中的一个错误。

您正在访问decimalDigits的越界元素。

在UB 之前尝试这3行

        if (digitIndex < 0 || digitIndex >= 3) {
            fprintf(stderr, "error %dn", __LINE__);
        }
        decimalDigits[digitIndex]++;

最新更新