How do I sort this array of pointers without changing the sort of the original array?
I made this file to work out some confusion I had with pointers and arrays of pointers. I understand up until the commented out code, and am able to change the order of the values in p_to_pointers without changing p_to_nums. But I'm having trouble translating it to qsort.
Here is my output:
0 p_to_nums: 7 p_to_pointers: 7
1 p_to_nums: 4 p_to_pointers: 4
2 p_to_nums: 4 p_to_pointers: 4
3 p_to_nums: 2 p_to_pointers: 2
4 p_to_nums: 1 p_to_pointers: 1
This is the desired output:
0 p_to_nums: 4 p_to_pointers: 7
1 p_to_nums: 2 p_to_pointers: 4
2 p_to_nums: 7 p_to_pointers: 4
3 p_to_nums开发者_开发百科: 4 p_to_pointers: 2
4 p_to_nums: 1 p_to_pointers: 1
And my code:
int compare_values (const void *a, const void *b) {
const int *int_a = (const int *) a;
const int *int_b = (const int *) b;
return (*int_b > *int_a) - (*int_b < *int_a);
}
main() {
int i;
int nums[5];
int *p_to_nums;
int *p_to_pointers[5];
nums[0] = 4;
nums[1] = 2;
nums[2] = 7;
nums[3] = 4;
nums[4] = 1;
p_to_nums = &nums[0];
for (i=0; i< 5; i++) {
p_to_pointers[i] = &p_to_nums[i];
}
//p_to_pointers[0] = &p_to_nums[2];
//p_to_pointers[2] = &p_to_nums[0];
qsort(*p_to_pointers, 5, sizeof(int), compare_values);
for (i=0; i< 5; i++) {
printf("%d p_to_nums: %d p_to_pointers: %u\n", i, (p_to_nums[i]), *p_to_pointers[i]);
}
return 0;
}
You are sorting *p_to_pointers with sizeof(int) whereas I believe you want to sort p_to_pointers sizeof(int *).
compare_values would need to be adjusted to dereference twice.
If…and this is a big if…I understand what you are trying to do.
Also, your comparison in compare() is needlessly complex. You can just do a simple subtraction instead of two comparisons and a subtraction.
int compare_values (const void *a, const void *b) {
const int **int_a = (const int **) a;
const int **int_b = (const int **) b;
return (**int_b - **int_a);
}
main() {
int i;
int nums[5];
int *p_to_nums;
int *p_to_pointers[5];
nums[0] = 4;
nums[1] = 2;
nums[2] = 7;
nums[3] = 4;
nums[4] = 1;
p_to_nums = &nums[0];
for (i=0; i< 5; i++) {
p_to_pointers[i] = &p_to_nums[i];
printf("%d p_to_nums: %d p_to_pointers: %u\n", i, (p_to_nums[i]), *p_to_pointers[i]);
}
qsort(p_to_pointers, 5, sizeof(int *), compare_values);
for (i=0; i< 5; i++) {
printf("%d p_to_nums: %d p_to_pointers: %u\n", i, (p_to_nums[i]), *p_to_pointers[i]);
}
return 0;
}
Output:
0 p_to_nums: 4 p_to_pointers: 4
1 p_to_nums: 2 p_to_pointers: 2
2 p_to_nums: 7 p_to_pointers: 7
3 p_to_nums: 4 p_to_pointers: 4
4 p_to_nums: 1 p_to_pointers: 1
0 p_to_nums: 4 p_to_pointers: 7
1 p_to_nums: 2 p_to_pointers: 4
2 p_to_nums: 7 p_to_pointers: 4
3 p_to_nums: 4 p_to_pointers: 2
4 p_to_nums: 1 p_to_pointers: 1
The first argument to qsort
is *p_to_pointers
. That is the same as p_to_pointers[0]
which you have set to &p_to_nums[0]
. That, in turn is the same as p_to_nums
. So you call to qsort
ends up being equivalent to
qsort(p_to_nums, 5, sizeof(int), compare_values);
Thus, you are sorting p_to_nums
.
What you want is
qsort(p_to_pointers, 5, sizeof(int*), compare_values);
Then your compare_values has to convert the void*
to int**
rather than int*
, and you need an extra level of indirection in your dereferences. The usual way to accomplish the comparison would be something like this:
int compare_values (const void *a, const void *b) {
const int **int_a = a;
const int **int_b = b;
return **int_b - **int_a;
}
Note that in C the casts from void*
are not necessary (though in C++ they are). Also note the more typical subtraction in the return
statement, rather than your rather unusual construct (though yours works).
精彩评论