Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

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

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...