2009-03-05 35 views
5

Tôi gặp sự cố khi biên dịch chương trình mẫu được trình bày trong phần 5.11 của cuốn sách. Tôi đã xóa hầu hết mã và chỉ để lại nội dung có liên quan.Sự cố khi biên dịch mẫu K & R

#define MAXLINES 5000 
char *lineptr[MAXLINES]; 

void qsort1(void *lineptr[], int left, int right, int (*comp)(void *, void *)); 
int numcmp(char *, char *); 

main(int argc, char *argv[]) { 
    int numeric = 1; 
    /* ... */ 
    qsort1((void**) lineptr, 0, 100, (int (*)(void*, void*))(numeric ? numcmp : strcmp)); 
} 

void qsort1(void *v[], int left, int right, int (*comp)(void *, void *)) { 
    /* ... */ 
} 

int numcmp(char *s1, char *s2) { 
    /* ... */ 
} 

Vấn đề là mã không biên dịch (Tôi đang sử dụng trình biên dịch sao Hỏa kỹ thuật số). Lỗi tôi nhận được là:

 qsort1((void**) lineptr, 0, nlines - 1, (int (*)(void*, void*))(numeric 
? numcmp : strcmp)); 

       ^
go.c(19) : Error: need explicit cast to convert 
from: int (*C func)(char const *,char const *) 
to : int (*C func)(char *,char *) 
--- errorlevel 1 

Có điều gì đó sai với khai báo mặc dù tôi đã dán mã từ sách chính xác. Tôi không biết đủ để thực hiện các thay đổi đúng (phần về các con trỏ hàm có thể được viết nhiều hơn).

EDIT: Tôi nên đề cập rằng tôi đang đọc phiên bản ANSI của cuốn sách.

+0

là bạn biên soạn như một chương trình C hoặc C++ chương trình –

+0

tôi có thể tưởng tượng rằng cũ K & R mã đã không biết const. thử xác định hàm của bạn là int numcmp (char const * s1, char const * s2) {} –

+0

@ litb: điều này dường như đã hoạt động. – Ree

Trả lời

8

Tôi nghĩ rằng lỗi đến từ thực tế là C cũ không biết const nào: strcmp có hai con trỏ đến các ký tự không const (char *) tôi nghĩ (đó có thể là lý do tại sao nó được biên dịch lại, nhưng không phải với trình biên dịch của bạn). Tuy nhiên, ngày nay strcmp mất char const* (const char* là giống nhau). Thay đổi mẫu chức năng của bạn như thế này:

int numcmp(char const*, char const*); 
+0

qsort1() chữ ký cần phải thay đổi quá;) – dirkgently

+0

thực sự có nhiều thứ phải lo lắng. anh ta nên cho tham số của numcmp void *, void * thay vì trỏ tới char. nhưng anh ta muốn lấy ví dụ từ cuốn sách để biên dịch. tôi không muốn thay đổi toàn bộ mã của ví dụ của cuốn sách –

0

Đã một thời gian kể từ khi tôi thực hiện bất kỳ chương trình C thuần túy nào, tôi không chắc chắn về tiêu chuẩn mới.

Tuy nhiên truyền để void ** tạo một con trỏ tới một con trỏ trong đó hàm cần một con trỏ tới một mảng. Chắc chắn, họ là những điều tương tự trong nội bộ, nhưng typechecking mạnh mẽ sẽ bắt mà là một lỗi.

viết lại qsort để chấp nhận ** thay vì * [] và bạn sẽ ổn.

+0

cũng ông đã chấp nhận **. * foo [] trong một prototype nguyên mẫu sẽ cho nó cùng kiểu như ** foo :) không phải là lỗi nhưng nó thường bị nhầm lẫn bởi các lập trình viên –

2

Con trỏ chức năng tiêu chuẩn mong đợi bởi qsort() hoặc bsearch() có nguyên mẫu:

int comparator(const void *v1, const void *v2); 

Các qsort1() quy định tại các mã hy vọng:

int comparator(void *v1, void *v2); 

Các chức năng so sánh được xác định trong các mã không có mà nguyên mẫu và không có chuyển đổi tự động giữa các loại con trỏ hàm khác nhau.

Vì vậy, bản sửa lỗi cho qsort1() là một trong hai:

  1. giới thiệu một dàn diễn viên: (int (*)(void *, void *)), hoặc
  2. Viết lại các bộ so sánh:

    int numcmp(void *v1, void *v2) 
    { 
        char *s1 = v1; 
        char *s2 = v2; 
        ... 
    } 
    
    int str_cmp(void *v1, void *v2) // Note new function name! 
    { 
        return(strcmp(v1, v2)); 
    } 
    

Rõ ràng, cuộc gọi đến qsort1() sẽ tham chiếu str_cmp thay vì strcmp. Các tác giả đã tìm cách tránh một hàm trung gian, nhưng lại chạy các trình biên dịch fussier (hợp pháp) được sử dụng ngày nay.

Phiên bản tiêu chuẩn của qsort() sẽ yêu cầu một loạt các loại vòng loại const, như trong phiên bản đầu tiên của câu trả lời này.

+0

Anh ta đang sử dụng một hàm tùy chỉnh có tên là qsort(). – dirkgently

+0

Vâng, vâng: qsort1() là pedantically pedantic. Và qsort1() có một kỳ vọng khác; Tôi sẽ chỉnh sửa. –

2

Đó là một vấn đề phổ biến :)

Các dòng sau nói qsort để mong đợi một con trỏ tới một hàm với hai tham số * void.Thật không may, strcmp mất hai chuỗi không thể thay đổi do đó nó là chữ ký là

int (*comp)(const char*, const char*) 

thay vì những gì bạn có:

int (*comp)(void *, void *) 

Thay đổi chữ ký của cả hai qsort1numeric:

qsort1(void *v[], int left, int right, int (*comp)(const void *, const void *)) 

và :

int numcmp(const char*, const char*) 
+0

Chữ ký của qsort1() bạn đã viết đã giống với chữ ký trong ví dụ của tôi. – Ree

+0

Tôi nhận ra rằng khoảng một phút rưỡi trước bạn;) – dirkgently

1

Lưu ý rằng strcmp mất hai const lập luận, trong khi numcmp của bạn thì không. Do đó, hai loại chức năng không khớp, và toán tử ? : sẽ khiếu nại.

Đừng một trong số:

  1. thay đổi numcmp để phù hợp với nguyên mẫu strcmp về constness
  2. đẩy các (int (*)(void*, void*)) cast bên trong ? :, ví dụ

    numeric ? (int (*)(void*, void*))numcmp : (int (*)(void*, void*))strcmp 
    
Các vấn đề liên quan