了解改组功能

时间:2019-05-30 18:49:23

标签: c

我在this thread上发现了以下用于改组任何类型的数据类型的功能:

#define NELEMS(x)  (sizeof(x) / sizeof(x[0]))

/* arrange the N elements of ARRAY in random order.
 * Only effective if N is much smaller than RAND_MAX;
 * if this may not be the case, use a better random
 * number generator. */
static void shuffle(void *array, size_t n, size_t size) {
    char tmp[size];
    char *arr = array;
    size_t stride = size * sizeof(char);

    if (n > 1) {
        size_t i;
        for (i = 0; i < n - 1; ++i) {
            size_t rnd = (size_t) rand();
            size_t j = i + rnd / (RAND_MAX / (n - i) + 1);

            memcpy(tmp, arr + j * stride, size);
            memcpy(arr + j * stride, arr + i * stride, size);
            memcpy(arr + i * stride, tmp, size);
        }
    }
}

我一直在测试,它似乎可以正常工作,但是我很难理解它的工作方式和原因。

  1. 如何以及为什么不直接在array上交换数组的元素
  2. 为什么可以将数组分配给char *:char *arr = array;
  3. memcpy函数中的偏移量i * stridej * stride大于数组的总大小(sizeof(array))。指针算术在这里如何工作?

2 个答案:

答案 0 :(得分:1)

为了更好地理解,我将调整应答顺序:

2-{{​​1}}是类型array的指针。在C语言中,可以向类型void的指针分配指针。指向对象的任何指针都可以转换为类型void*,而不会丢失信息。如果将结果转换回原始指针类型,则将恢复原始指针。

1-它对单个元素的工作方式不同,您没有可以分配给任何类型的通用类型。因此,代码正在切换指向内存的内容。

3-void*是数组中元素的数量,而n是数组中单个元素的大小。 size表示stride = size * sizeof(char);等于stride,因为size等于1。数组sizeof(char)的大小等于sizeof(array)-元素数数组中的元素乘以元素的大小。由于n * sizei均小于j,因此ni * stride 永远不会大于数组使用的内存。我不知道为什么据我所知j * stride总是使用stride

答案 1 :(得分:0)

  1. array的类型为void*。它只是一个没有解释的指针,所以我们不知道它指向什么数据类型。元素的数量为int n,每个元素的大小为size。这样做是为了使该函数可以与任何类型的数组一起使用。
  2. char *arr = array;将void指针解释为指向字节序列。
  3. sizeof(array)给出了 pointer 的大小,而不是实际数组的大小。实际的字节大小为i * size

随机播放算法似乎是Fisher-Yates Shuffle

我还将注意到* sizeof(char)是毫无意义的,因为sizeof(char)根据定义为1。