Tôi viết một chức năng tiếp nhận một con trỏ tới một hàm so sánh và một mảng của MyStructs
và được cho là để sắp xếp mảng theo chức năng so sánh:Đúc chức năng con trỏ
void myStructSort(
struct MyStruct *arr,
int size,
int (*comp)(const struct MyStruct *, const struct MyStruct *)) {
qsort(arr, size, sizeof(struct MyStruct), comp);
}
Thật không may điều này không biên dịch vì qsort
hy vọng bộ so sánh sẽ nhận được các đối số void *
chứ không phải const struct MyStruct *
. Tôi nghĩ về một số giải pháp tồi và đã tự hỏi giải pháp chính xác là gì.
Lựa chọn 1
Cast comp
-int (*)(const void *, const void*)
. Biên dịch này nhưng là hành vi không xác định (xem this SO question).
Lựa chọn 2
Tạo một biến toàn cầu int (*global_comp)(const struct MyStruct *, const struct MyStruct *)
và thiết lập global_comp=comp
bên myStructSort
. Sau đó, tạo một hàm:
int delegatingComp(const void *a, const void *b) {
return globalComp((const struct MyStruct *)a, (const struct MyStruct *)b);
}
Và trong myStructSort
gọi qsort(arr, size, sizeof(struct MyStruct), delegatingComp)
. Vấn đề với điều này là biến toàn cục icky.
Lựa chọn 3
reimplement qsort
. Đây là thực hành an toàn về mặt chức năng nhưng rất kém.
Có lựa chọn thứ tư hoàn hảo kỳ diệu không?
Sửa
tôi không thể thay đổi API của myStructSort
và tôi biên soạn mã của tôi sử dụng gcc c99 -Wall -Wextra -Wvla
.
Trong trường hợp đó, hàm bao bọc như hàm bạn đã đưa ra trong tùy chọn 2 là cách tiếp cận tốt nhất. Btw, tbh Tôi đã không hoàn toàn có được ý tưởng về các biến toàn cục mà bạn đã đề cập. Chúng là gì? – HighPredator
HighPredator @, 'delegatingComp' cần biết hàm nào cần gọi và nó không thể được truyền cho nó như một đối số vì nó cần khớp với đối số' qsort'. –
nếu bạn đang sử dụng 'gcc', phần mở rộng gnu cho phép bạn xác định một hàm phụ bên trong một hàm. nó mô phỏng một đóng cửa dựa trên ngăn xếp. nếu bạn không nhớ thiệt hại về tính di động, bạn có thể thử điều đó. – HuStmpHrrr