2009-03-20 30 views
7

thể trùng lặp:
Problem compiling K&R examplePointer cảnh báo loại không phù hợp trong ví dụ từ K & R C

Gần đây tôi đã làm việc cách của mình thông qua ngôn ngữ lập trình C của K & R.

Trong phần 5.11, chúng bao gồm các con trỏ đến các hàm và sau khi nhập vào ví dụ của chúng - một triển khai thực hiện nhanh nơi chúng ta cung cấp một con trỏ tới compari chức năng con trai chúng tôi muốn sử dụng - Tôi nhận được một cảnh báo từ trình biên dịch: loại con trỏ không khớp trong biểu thức điều kiện. (Trình biên dịch của tôi là 4.0.1 gcc trên OS X 10.5.6)

Dòng từ ví dụ kích hoạt cảnh báo là: chương trình

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

Các thực thi mà không segfaulting, nhưng tôi muốn Smoosh mỗi cảnh báo Tôi có thể, hoặc ít nhất là hiểu nguyên nhân của họ.

Việc kê khai chức năng cho numcmp trông giống như:

int numcmp(char *, char *); 

Nhưng theo manpage, stcmp có chữ ký này:

int strcmp(const char *s1, const char *s2); 

là cảnh báo đơn giản vì chữ ký phương pháp hơi khác nhau? Hậu quả của việc bỏ qua cảnh báo là gì?

+0

Eddie chỉ về một bản dupe. Tôi đã bỏ phiếu để đóng câu hỏi của riêng mình nhưng tôi nghĩ rằng sẽ có một cách mà chủ sở hữu có thể đóng nó lại. – Dana

+0

Dana, hãy xem [Vấn đề biên soạn ví dụ K & R] (http://stackoverflow.com/questions/616906/problem-compiling-kr-example/616929) và có thể bạn sẽ tìm thấy câu trả lời cho câu hỏi của mình ở đó. Hãy cho chúng tôi biết nếu bạn không biết. – Eddie

Trả lời

1

Một cách để thử và chẩn đoán nó là để xem điều gì sẽ xảy ra nếu bạn thay thế biểu thức bằng?: Chỉ với một trong hai.

Nếu nó chỉ xảy ra cho strcmp chứ không phải numcmp, thì nó có thể rất tốt là vì const char *. Tôi nghĩ rằng trong khi char * luôn có thể được chuyển đổi thành void *, bạn không thể chuyển đổi const char * thành void * thành "an toàn".

Nếu nó có cả hai, thì có lẽ đây là vấn đề với con trỏ hàm, trong đó có ký hiệu char * được chuyển thành void *, nhưng chữ ký phải giống nhau và có khoảng trống thay vì ký tự là một vấn đề.

3

Câu trả lời ngắn: K & R không biết C.

Long trả lời: Họ đã bị trói tay bởi thực tế là khi họ bắt đầu, không ai biết C, vì vậy họ đã loại làm cho nó lên như họ đã đi cùng.

(Hơi) hình thức ít thiếu nghiêm túc của câu trả lời dài: Ngôn ngữ đã phát triển (một số sẽ nói thay đổi) khá một chút kể từ khi K & R được viết ra, nhưng trừ khi bạn có phiên bản e-book với ví dụ động morphing, các ví dụ trong bản sao của bạn của K & R sẽ không bắt kịp với ngôn ngữ "mới và được chấp thuận" ("bây giờ với nhiều hơn ANSI!").

7

Mặc dù bạn hoàn toàn có thể truyền char * vào khoảng trống *, nhưng bạn không thể thực hiện tương tự cho con trỏ hàm với các loại đó (không có cảnh báo). Trình biên dịch cẩn thận hơn với kiểu khớp trên các chữ ký chức năng.

Chưa kể rằng những gì đang xảy ra bên trong qsort sẽ ngược lại: tức là, một khoảng trống * sẽ được đúc thành một char * trong numcmp và const char * trong strcmp.

Và trình biên dịch sẽ đưa ra cảnh báo trong những trường hợp này. Nếu bạn thực sự phải sử dụng một hàm không có cùng kiểu với tham số, có lẽ bạn nên sử dụng hàm bao hàm phù hợp với các loại, và sau đó thực hiện phép đúc rõ ràng thích hợp khi gọi hàm ban đầu.

Ví dụ:

static int strcmp_wrapper(void* s1, void* s2) { 
    return strcmp((char*)s1, (char*)s2); 
} 

static int numcmp_wrapper(void* n1, void* n2) { 
    return numcmp((char*)n1, (char*)n2); 
} 

qsort((void **) lineptr, 0, nlines-1, 
     (numeric ? numcmp_wrapper : strcmp_wrapper)); 

Và chữ ký hiện đại cho qsort là

void 
qsort(void *base, size_t nel, size_t width, 
     int (*compar)(const void *, const void *)); 

Vấn đề const dường như không đi vào chơi trong câu hỏi của bạn, nhưng K & R không có const.

+0

Một tùy chọn khác là thay đổi biểu thức thứ ba thành: số? (int (*) (void *, void *)) numcmp: (int (*) (void *, void *)) strcmp); Vì vậy, chỉ cần chuyển hai hàm khác nhau riêng biệt với qsort. Điều này cũng sẽ tránh bất kỳ cảnh báo nào được đưa ra bởi trình biên dịch – bryanph

Các vấn đề liên quan