我在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);
}
}
}
我一直在测试,它似乎可以正常工作,但是我很难理解它的工作方式和原因。
array
上交换数组的元素char *arr = array;
i * stride
或j * stride
大于数组的总大小(sizeof(array)
)。指针算术在这里如何工作?答案 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 * size
和i
均小于j
,因此n
和i * stride
永远不会大于数组使用的内存。我不知道为什么据我所知j * stride
总是使用stride
。
答案 1 :(得分:0)
array
的类型为void*
。它只是一个没有解释的指针,所以我们不知道它指向什么数据类型。元素的数量为int n
,每个元素的大小为size
。这样做是为了使该函数可以与任何类型的数组一起使用。char *arr = array;
将void指针解释为指向字节序列。sizeof(array)
给出了 pointer 的大小,而不是实际数组的大小。实际的字节大小为i * size
。随机播放算法似乎是Fisher-Yates Shuffle。
我还将注意到* sizeof(char)
是毫无意义的,因为sizeof(char)
根据定义为1。