Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
171 views
in Technique[技术] by (71.8m points)

c - Understanding a shuffling function

I found on this thread the following function to shuffle any kind of data types:

#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);
        }
    }
}

I have been testing and it seems to work fine but I'm having a hard time understanding how and why it works.

  1. How and why doesn't it swap an element of the array directly on array
  2. How come it is possible to assign array to a char*: char *arr = array;
  3. The offset i * stride or j * stride in memcpy functions is bigger than the total size of the array (sizeof(array)). How come the pointer arithmetic works here?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

For better understanding I will shuffle the answering order:

2 - array is a pointer of type void. In C, pointers may be assigned to and from pointers of type void*. Any pointer to an object may be converted to type void* without loss of information. If the result is converted back to the original pointer type, the original pointer is recovered.

1 - It does not work the same for single elements, you do not have a generic type that can be assigned to any type. So the code is switching the content of pointed memory.

3 - n is the number of elements in array, while size is the size of a single element in the array. stride = size * sizeof(char); means stride is equal to size, as sizeof(char) equals 1. The size of the array sizeof(array) equals n * size - the number of elements in the array multiplied with the size of an element. Since both i and j are less than n, i * stride and j * stride will never be greater than the memory used by the array. I wonder though why the use of this stride, as far as I know sizeof(char) is always 1.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...