2009-03-20 20 views
7

可能性の重複:私はR.ポインタ型の不一致の警告

K &でCプログラミング言語を通じて自分の道を働いてきた
Problem compiling K&R example

最近

5.11節では、関数へのポインタとその例を入力した後のクイックソートの実装について説明します。クイックソートの実装では、私が使用したい息子関数 - コンパイラから警告が出ます:条件式のポインタ型の不一致。 (私のコンパイラは、OS X 10.5.6上のGCC 4.0.1です)

警告をトリガーする例から行は次のとおりです。

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

プログラムはセグメンテーションフォルトなしで実行されますが、私はすべての警告をsmooshしたいです私はその原因を知ることができる、または少なくとも理解する。

numcmpのための関数の宣言は次のようになります。

int numcmp(char *, char *); 

しかし、manページによると、stcmpこのシグネチャがあります。

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

があるため、わずかに異なる方法で署名の警告シンプルですか?警告を無視するとどうなるのでしょうか?

+0

エディは嘘について指摘しています。私は自分の質問を終えるように投票しましたが、所有者が簡単にそれを閉じる方法があると思いました。 – Dana

+0

Dana、[K&Rサンプルをコンパイルする際の問題点](http://stackoverflow.com/questions/616906/problem-compiling-kr-example/616929)をご覧ください。あなたがしなければ私たちに知らせてください。 – Eddie

答えて

1

これを試して診断する1つの方法は、式を?:で置き換えるとどうなるかを確認することです。

stmcmpではなくnumcmpだけが発生した場合、const char *が原因である可能性があります。 char *は常にvoid *に変換できますが、const char *をvoid *に「安全に」変換することはできません。

もし両方であれば、おそらく関数ポインタに関しては問題があるかもしれませんが、char *をvoid *に変換すると動作しますが、署名は同一でなければならず、charsの代わりにvoidsが問題になります。

3

短い答え:K & Rは、Cを知らなかった

長い答え:彼らは、彼らが始めたとき、がCを知っていたという事実によってハンディキャップされたので、彼らは一種のようにそれを作っていました彼らは一緒に行った。

(わずかに)長い答えの少ない軽薄形式:K & Rが書かれていたので、かなり(一部はを変え言う)が、言語が進化しているあなたは、動的な例で電子書籍版を得ない限り、モーフィングでは、K & Rの例は、「新しい承認済み」言語(「もっとANSI!」の言語)に追いついていないでしょう。

7

void *に暗黙的にchar *をキャストすることはできますが、これらの型の関数ポインタについては(警告なしで)同じことをすることはできません。コンパイラは関数シグネチャの型の照合に注意します。

qsortの内部で起こっていることは反対であることは言うまでもありません。すなわち、void *はnumcmpのchar *に、strcmpのconst char *にキャストされます。

これらの場合、コンパイラは警告を発行する必要があります。パラメータと同じ型を持たない関数を実際に使用する必要がある場合は、型にマッチするラッパー関数を使用し、元の関数を呼び出すときに適切な明示的キャストを行う必要があります。例えば

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

とのqsortのための現代的な署名が

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

あるconstの問題は、あなたの質問に遊びに来ていないようだが、K & Rはしませんでした持っているconst

+0

別のオプションは、三項式を次のように変更することです: 数値? (int(*)(void *、void *))numcmp:(int(*)(void *、void *))strcmp); したがって、2つの異なる関数をqsortに別々に渡すだけです。これにより、コンパイラからの警告も回避されます。 – bryanph