2009-03-20 27 views
7

Olası Çoğalt: Ne R.Pointer tür uyumsuzluğu uyarı

K & tarafından C Programlama Dili ile yoluma çalışıyoruz
Problem compiling K&R example

Son zamanlarda

Bölüm 5.11'de, işlevlere ve örneklerine yazdıktan sonra işaretçileri kapsamaktadır - compari'ye bir işaretçi sağladığımız bir fastsort uygulaması kullanmak istediğimiz fonksiyon - derleyiciden bir uyarı alıyorum: koşullu ifadede işaretçi türü uyuşmazlığı. uyarıyı tetikleyen örnekten

çizgi edilir (My derleyici OS X 10.5.6 üzerinde gcc 4.0.1):

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

programı segfaulting olmadan yürütür, ama ben her uyarıyı smoosh ister Onların sebeplerini anlayabilir veya en azından anlayabilirim.

int numcmp(char *, char *); 

Ama man sayfasına göre, stcmp bu imzası vardır:

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

mi çünkü biraz farklı yöntem imzaların basit uyarı

numcmp için fonksiyon bildirimi benziyor? Uyarıyı ihmal etmenin sonuçları nelerdir?

+0

Eddie bir dupe hakkında işaret etti. Kendi sorumu kapatmaya oy verdim, ancak sahibin onu kapatabileceği bir yol olacağını düşündüm. – Dana

+0

Dana, [Sorun derleme K & R örneği] 'ne bakın (http://stackoverflow.com/questions/616906/problem-compiling-kr-example/616929) ve muhtemelen sorunuzun cevabını burada bulabilirsiniz. Eğer yapmazsan haber ver. – Eddie

cevap

1

Bunu denemenin ve teşhis etmenin bir yolu, ifadeyi?: Ile ikisinden biri ile değiştirirseniz ne olacağını görmek.

Yalnızca strcmp için değil, numcmp içinse, o zaman const char * 'dan dolayı olabilir. Char * * her zaman void * 'e dönüştürülebilse de, const char *' i * void * 'i "güvenli" olarak değiştiremezsiniz.

Eğer her ikisiyle de varsa, belki de bu, char * * void * işinin dönüştürüldüğü, ancak imzaların özdeş olması ve char'lar yerine boşluklara sahip olmasının bir sorun olduğu, işlev işaretçileriyle ilgili bir sorunla ilgilidir.

3

Kısa cevap: K & R C bilmiyordum

Uzun cevap: Onlar başladığında, kimse C bildiği gerçeğiyle engelli edildi, bu yüzden tür olarak o kadar kazanıyorduk onlar gitti.

(Hafif) uzun cevabın az saygısız formu: K & R yazılmıştır beri biraz (bazı değişmiş söyleyebilirim), ama dil gelişti dinamik örnekle e-kitap versiyonu var sürece morphing, K & R kopyanızdaki örnekler "yeni ve onaylanmış" ("şimdi daha da fazla ANSI!") diliyle kalmamıştı.

7

Bir char * öğesini bir boşlukta * dolaylı olarak yayınlayabilmenize rağmen, aynı türde bir işlev işaretçisi için (uyarı olmadan) aynısını yapamazsınız. Derleyici, işlev imzaları üzerinde tür eşleme ile daha dikkatlidir.

qsort içinde neler olup bittiğini belirtmek tam tersi olacaktır: yani, bir void * strcmp'de numcmp ve const char * karakterinde bir char * olarak gösterilecektir.

Ve derleyici bu durumlarda bir uyarı vermelidir. Gerçekten, parametrelerle aynı türde olmayan bir işlevi kullanmanız gerekiyorsa, belki de türlerle eşleşen bir sarmalayıcı işlevini kullanmanız ve özgün işlevi çağırırken uygun açıklamalı yayınlama yapmalısınız. Örneğin

:

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)); 

Ve qsort modern imza const konusu sorunuzu devreye girer görünmüyor, ancak K & R vermedi

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

olduğunu const var.

+0

Üçlü ifadeyi aşağıdaki gibi değiştirmek için başka bir seçenek: sayısal? (int (*) (void *, void *)) numcmp: (int (*) (void *, void *)) strcmp); Bu yüzden iki farklı işlevi ayrı olarak qsort'a aktarın. Bu ayrıca derleyici tarafından verilen uyarılardan da kaçınacaktır. – bryanph