1

単純なmerge関数を実装していますが、説明できないエラーがコンパイラーから出されて行き詰まりました。これが私のmerge機能です:

void merge(void *a, int beg, int middle, int end, int (*cmp)(const void*, const void*
{
  std::stack<void*> first;
  std::stack<void*> second;

  for(int i = beg; i < middle; i++) {
   first.push(a+i);
  }
  for(int i = middle; i < end; i++) {
    second.push(a+i);
  }

  for(int i = beg; i < end; i++) {
    if(first.empty()) {
      void *tmp = second.top();
      second.pop();
      a+i = tmp;
    } else if(second.empty()) {
      void *tmp = first.top();
      first.pop();
      a+i = tmp;
    } else if(cmp(first.top(), second.top())) {
      void *tmp = first.top();
      first.pop();
      a+i = tmp;
    } else {
      void *tmp = second.top();
      second.pop();
      a+i = tmp;
    }
  }
}

そして、ここにエラーがあります:

sort.h: In function `void merge(void*, int, int, int, int (*)(const void*, const void*))':
sort.h:9: error: pointer of type `void *' used in arithmetic
sort.h:12: error: pointer of type `void *' used in arithmetic
sort.h:19: error: pointer of type `void *' used in arithmetic
sort.h:19: error: non-lvalue in assignment
sort.h:23: error: pointer of type `void *' used in arithmetic
sort.h:23: error: non-lvalue in assignment
sort.h:27: error: pointer of type `void *' used in arithmetic
sort.h:27: error: non-lvalue in assignment
sort.h:31: error: pointer of type `void *' used in arithmetic
sort.h:31: error: non-lvalue in assignment

誰でも私を助けることができますか?ティア。

4

5 に答える 5

4

void*にはサイズがなく、voidポインタ演算では型のサイズに基づいてメモリ アドレスを計算する必要があるため、ポインタ演算は では不可能です。

を期待し、バイト オフセットを表す場合は、beg代わりポインターを使用する必要があります(1は 1 バイトです)。middleendcharchar

任意の型で動作するジェネリック関数を書きたい場合は、voidポインターではなくテンプレートを使用してください。

template <typename t>
void merge(T *a, int beg, int middle, int end, int (*cmp)(const T*, const T*))
{
    // ...
}
于 2012-06-28T15:14:25.757 に答える
1

の問題void*は、タイプのないアドレスであることです。あなたが尋ねるときは、要素の種類を指定せずに「要素をさらにa+i移動してください」と言ってください。i1 バイト、1 int、1 車、1 家、または 1 大陸ですか?

C++ では、この種のものを使用する必要はありません。テンプレートを使用して、コンパイラにさまざまな型の処理方法を理解させることができます。

template<class T>
void merge(T* a, etc.
于 2012-06-28T15:18:38.173 に答える
1

関数プロトタイプはおそらく次のようになります。

void merge(void **a, int beg, int middle, int end, int (*cmp)(const void*, const void*));

その後、すべての配列メンバーにインデックスで問題なくアクセスできます。

注: void が指すオブジェクトのサイズは、Ferdinand が以前に述べたように不明です (したがって、a + i を適用できません)。しかし、void* のサイズはわかっているため、そのような方法でプロトタイプを更新するとうまくいきます。

于 2012-06-28T15:20:29.957 に答える
1

では、ポインターにオフセットをfirst.push(a+i);追加しようとしています。これは違法です。ivoid *a

何かが定義され、メモリ内に定義されたサイズがあるため、他の「何かのポインター」にオフセットを追加できます。したがって、オフセット 1 を追加するとsizeof(something)、メモリ内で前方に移動することになります。しかしvoid、定義されたサイズはありません。void *したがって、ポインターでオフセットを使用することはできません。

于 2012-06-28T15:14:14.960 に答える
0

エラーの 1 つについてお話しできます。でポインター演算を実行しようとしていますvoid*。ポインターに追加すると、ポインターの型に含まれるバイト数が追加されます。したがって、 a に追加すると、型void*がないため、コンパイラは追加するバイト数を知ることができませんvoid*。したがって、バイト レベルで実行する場合は、char*、または必要なその他のポインター レベルにキャストします。バイト単位で処理したい場合は、 を取得できますが、void*にキャストできchar*ます。

于 2012-06-28T15:15:48.013 に答える