3

qsortのような同様の「汎用」プロシージャがあります。これには、voidポインタ(配列を指す)と関数ポインタパラメータがあります。この関数は、どのタイプの配列でも機能するはずです。

例:

void do_something(void * array, int count, int size, void (*test)(const void*)){
    int i;
    for(i=0; i<count; i++){
        test(array + (index * size));
    }
}

ただし、これにより次の警告が表示されます (gcc test.c -pedantic-errors):

error: pointer of type ‘void *’ used in arithmetic [-Wpedantic]

そして、いくつかの調査の結果、このような void ポインターを使用するのは悪い習慣であることがわかりました。(例: C の void ポインターのポインター演算)

では、標準ライブラリは qsort のようなものをどのように処理するのでしょうか? このコード ( http://aturing.umcs.maine.edu/~sudarshan.chawathe/200801/capstone/n/qsort.c ) を見ると、次のようになります。

void
_quicksort (void *const pbase, size_t total_elems, size_t size,
        __compar_fn_t cmp)
{
  register char *base_ptr = (char *) pbase;
  ....
  char *lo = base_ptr;
  char *hi = &lo[size * (total_elems - 1)];
  ...
}

実際の型に関係なく (char *) にキャストしていますか?

4

3 に答える 3

3

私は同様の質問をしましたCでvoid *ポインターで算術演算を行うことはできますか? .

Void * 演算は定義されていません。void ポインタに 1 を加えるとはどういう意味ですか? ほとんどのコンパイラ (許可されている場合) は、 sizeof(char) (「次のバイト」) だけインクリメントするものとして扱いますが、警告します。

したがって、正しいことは、明示的にやりたいことを実行させることです-> char* にキャストし、それをインクリメントします

于 2015-10-15T17:04:38.957 に答える
1

不完全なデータ型でのポインター演算voidは正当ではなく、それがコンパイラーの不満です。

ご覧のとおり_quicksort()、ポインターは定数であるため、ポインターが指しているアドレスを変更することはできません。ポインターで行われる算術演算はありませんvoid

于 2015-10-15T17:03:17.230 に答える
1

ポインターを無効にすると、ポインターの「コンテキスト」が取り除かれます。つまり、システムがポインターをどのように見るか、またはポインターが保持しているものは何でもです。

このため、コンパイラは void ポインターに対して算術演算を行いません。ポインター演算を行うために、コンパイラーは適切な変換を行うことができるようにポインターの型を知る必要があります (ポインターが int を保持している場合、32 ビットの加算を行わないか、少なくとも何かがうまくいかないことを知ってください!)。

このため、これを行う唯一の方法は、ポインターを何かにキャストして実行することです。ポインターが何を取得するかをよく知っていない限り、お勧めしません。void ポインターは、非常にダークなプログラミングです。

于 2015-10-15T17:11:48.550 に答える