2010-01-25 84 views
1

我的教授這樣定義在.h文件C編譯器抱怨無效(*)

void list_map(INTLIST* list, void (*f)(void *)); /*Applies a function to each element of the list */ 

我寫了這樣的功能:

void list_map(INTLIST* list, void (*f)(void *)) 
    { 
    INTLIST* pTemp=NULL; 

    if (list == NULL) 
    { 
     //list is empty 
    } 
    else 
     { 
     for(pTemp=list; pTemp->next!=NULL; pTemp=pTemp->next) 
      { 
      f(pTemp); //f is a function pointer we call list map from main like list_map(lst, list_sort) 
      }  
     } 
    } 

我把它稱爲主這樣的:

list_map(aList[i], (void*)list_sort); 

在windows環境下,沒有任何抱怨,但我必須在Linux環境下運行這個。我使用一個makefile來編譯所有的代碼,我得到這個警告和錯誤:

* C++ -O2 -c main.c main.c:在函數'int main(int,char **) ': main.c:53:warning:從字符串常量到'char *'的過時的轉換 main.c:123:錯誤:從'void()(INTLIST)'無效轉換爲'void()(空隙)」 main.c中:123:錯誤:初始化的參數2 '空隙list_map(intList中*,空隙()(空隙))' 化妝:*** [main.o]錯誤1 *

有人可以首先幫助處理錯誤,然後可能會發出警告嗎?

編輯部分:

有人問了list_sort功能,那就是:

void list_sort(INTLIST* list) 
{ 
    INTLIST* pTemp=NULL; 
    INTLIST* pTemp2=NULL; 

    pTemp=list;   //temp pointers to compare node values 
    pTemp2=list; 

    if (pTemp->next !=NULL)  //move to second node 
    { 
     pTemp2=pTemp2->next; 
    } 

    while(pTemp2 != NULL) 
    { 
     //we implement a selection sort 
     //check if incoming node->datum with each node in the list 
     //swap values if < 
     if (pTemp2->datum < pTemp->datum) 
     { 
     //swap the values 
     int temp = pTemp->datum; 
     pTemp->datum = pTemp2->datum; 
     pTemp2->datum = temp; 
     } 
     //advance the pointer 
     pTemp2=pTemp2->next; 
    } 
} 
+0

'list_sort'是什麼樣的? – ezod 2010-01-25 02:30:32

+0

你可以改變list_sort函數,還是由prof指定的?如果它是固定的,似乎你已經處理了一個強硬的手。 – BobS 2010-01-25 04:19:59

回答

1

第一張:你爲什麼要將C代碼編譯爲C++?。請用C編譯器編譯它。

list_sort()原型爲:

void list_sort(INTLIST* list); 

list_map()具有原型:

void list_map(INTLIST* list, void (*f)(void *)); 

這意味着,第二個參數list_map()是一個函數,它一個void *參數,返回void (沒有)。現在

,C標準保證,任何對象指針void *的轉換和背部是確定的,所以給出:

INTLIST *l; 
/* make l point to a valid INTLIST */ 
void *pl = l; 

這是確定:

list_sort(pl); 

需要注意的是,list_sort()可能已被宣佈爲:

void list_sort_generic(void *l); 

事實上,既然你教授在某些地方使用void *,他希望將您的列表擴展爲某種通用類型。

無論如何,你可以傳遞一個INTLIST *list_sort()list_sort_generic(),但list_sort_generic()可以傳遞任何對象的指針,而list_sort()只能傳遞INTLIST *(或void *,將其從一個INTLIST *轉換)。

即使list_sort()可以採取void *list_sort()的簽名不是:

void list_sort(void *l); 

所以,函數類型的list_sort()list_sort_generic()是不一樣的,不能互換。 list_map()預計list_sort_generic()是一種函數,但是正在獲得一種不同類型的函數。

既然你不能改變任何原型,你需要一個演員。現在,void *是C中的泛型類型,所以你會認爲這樣的演員將工作。但是,正如我之前所說的,只有對象指針可以轉換爲void *,並且可以移植回—而不是函數指針類型。因此,致電list_map()時,您需要將list_sort()轉換爲正確的類型。

正確的類型是void (*)(void *)。這是返回void並取void *的函數。

因此,調用應該是:

list_map(aList[i], (void (*)(void *))list_sort); 

但,既然list_sort()的類型和list_map()其第二個參數期望的類型是不一樣的,中投可能會或可能無法正常工作。你的教授給你「不太好」(即,錯誤)原型。要麼他應該一直宣稱類型泛型函數,要麼他應該保留所有的東西INTLIST *。通過走中途,他引入了一個本不應該在那裏的複雜演員,並且可能無法工作。我相信,如果你將這個引入到你的教授的關注中,他會承認這個疏忽。

希望有幫助。

+0

這些是我正在尋找寫得很好的細節的東西,我可能不太在乎我希望瞭解問題的答案,以充分利用和學習語言。 Alok +1加上接受這個徹底的答案。你可以寫一本書,我會買它。 – oJM86o 2010-01-25 16:30:49

2

如果你投你的回調到適當的功能類型?

list_map(aList[i], (void (*)(void*))list_sort); 
+1

「如果你得到的不是鴨子,直到你得到你想要的東西」 - 我很抱歉,但這是一個給初學者的不好答案... – LiraNuna 2010-01-25 04:14:56

+1

@LiraNuna:這是一項功課,他不能改變list_map的原型。我怕他的老師想讓他揍它,直到它像鴨子一樣嘎嘎叫。 – zneak 2010-01-25 04:26:44

+0

這會使警告消失,但是現在當函數在list_map()中調用時,它會調用未定義的行爲。 – Christoph 2010-01-25 10:46:47

2

好,

void list_sort(INTLIST* list) 

有錯誤簽名的

void list_map(INTLIST* list, void (*f)(void *)) 
+0

正確的答案。 – 2010-01-25 02:47:05

+0

一直試圖跟隨這個東西,因爲我也在學習C ...但我想我的問題是它看起來像list_map的無效(* f))(void *)是隻是一個函數指針?他可以改變void list_sort成爲什麼? void list_sort(void * list)? – JonH 2010-01-25 02:53:23

0

第二個參數傳遞在你的函數list_sort,參數爲INTLIST *list

 
list_map(aList[i], (void*)list_sort); 

通過查看頭,其函數原型是具有參數,其是類型的函數指針void *

 
void list_map(INTLIST* list, void (*f)(void *)) 
             ^^^^^^^^ 

函數指針*f具有與簽名匹配,因此衝突和編譯器生成的警告。由於*f指向list_sort,方法簽名不匹配。

如果你的函數原型有這個代替

 
void list_map(INTLIST* list, void (*f)(INTLIST *)) 

希望這有助於 最好的問候, 湯姆它的工作。

+0

無法更改教授定義的list_map原型,我們不允許更改這些原型。 – oJM86o 2010-01-25 03:01:00

2

list_sort()一個簡單的演員陣容足以使警告消失,但它不足以使實際工作:

的C-標準並不能保證一個INTLIST *void *具有兼容表示,即void (INTLIST *)void (void *)是不同的,不兼容的類型。當list_map()調用list_sort()通過你的void (*f)(void *)說法,C99部分6.3.2.3,§8適用:

If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

要使它符合標準,你必須寫一個包裝功能list_sort()

void list_sort_wrapper(void *list) 
{ 
    list_sort(list); 
} 

和使用它作爲參數傳遞給您的來電:

list_map(aList[i], list_sort_wrapper); 

而且,如果list_sort()實現ç (沒有檢查算法),它已經走上了列表,即對每個節點調用它根本沒有任何意義。

編輯:

好吧,list_sort()實際上並沒有進行排序整個名單 - 可以通過

list_map(list, list_sort_wrapper); 

命名方案能夠實現,是一個嚴重的跆拳道 - 如果功能不整理清單,稱之爲list_sort_step()list_select_head()什麼的,但請不要list_sort()

+0

list_map是一個映射函數,它只需要一個函數指針指向list_sort(),只要您調用list_map即可排序整個列表,即使list_sort正在逐個執行此元素。我知道這看起來很奇怪,但是教授們是真正無法編碼的陌生人。 – oJM86o 2010-01-25 16:25:48

+0

+1也是一個很好的解釋。 – oJM86o 2010-01-25 16:32:21