1

これは学校のプロジェクトのためのものですが、私の質問は特定の実装に関しては何の関係もありませんし、プロジェクト自体に関しても助けを求めているわけではありません。私が行っていることのコンテキストを提供したいので、この警告を出しているだけですが、これはプロジェクトのコンテキスト内でフレーム化された void ポインターのキャストに関する一般的な質問です...私が書いているこの関数は「そうではありません」プロジェクトの場合でも、データ構造の生成が機能しているかどうかを確認するためのテストメカニズムとして作成したものにすぎません...そして、printf()、フォーマット指定子、およびキャストに関連する問題につながります....私は基本的にリンクされたリスト (「キュー」と呼ばれますが、実際にはまったくキューではありません) を実装する必要があり、それをテストする関数を作成しました。

基本的に、いくつかの変数を持つ「チャンク」と呼ばれる構造体があります ( firstは、指定された「チャンク」の最初の要素である大きな配列内のインデックスであり、arrは基本的に large_array[c->first] ですが、実際にはvoid ポインター自体: void *arr (c はチャンクへのポインター)) は、より大きな配列内の位置を示します。したがって、基本的に、a = {5,7,3,4,6,9,1,2} のような配列があり、2 つのチャンク サイズが与えられた場合、それぞれに「arr」を持つ 4 つのチャンクがあります。それぞれ 5、次に 3、次に 6、次に 1 を指す void ポインタ変数。

とにかく、私は "print_queue" 関数 (実際にはチャンクのリンクされたリスト) を書きました。必要に応じてすべての情報が出力されます。ここで共有するコア部分を次に示します。

 while (index < num_chunks) {
    first = c->first;
    printf("Chunk %d: first is %d and a[%d] is ", index, first, first);
    if (elem_size == LONG_SIZE) /* LONG_SIZE defined above as 8 */
      printf("%ld\n", c->arr);
    else if (elem_size == INT_SIZE) /* INT_SIZE defined above as 4 */
      printf("%d\n", c->arr);
    else if (elem_size == CHAR_SIZE) /* CHAR_SIZE defined above as 1 */
      printf("%c\n", c->arr);

    index++;

    if (c->next != NULL)
      c = c->next;
 }

私は基本的に、プロジェクトの実際の機能 (マルチスレッド マージソート) を実装しながら、テスト目的で 3 つのタイプ (long、int、および char) のいずれかのリンク リストを出力できる関数を作成したいと考えていました。したがって、上記のコードは実際に機能します。これは、この配列入力の出力です。

 char original[] = {'z', 'y', 'x', 'w', 'v', 'u', 't', 's'};

出力:

 Chunk 0: first is 0 and a[0] is z
 Chunk 1: first is 2 and a[2] is x
 Chunk 2: first is 4 and a[4] is v 
 Chunk 3: first is 6 and a[6] is t

だからうまくいく!わーい!ただし、次のコンパイラ警告が表示されます。

mergesort.c: In function 'print_chunk_queue':
mergesort.c:85:7: warning: format '%ld' expects argument of type 'long int', but     argument 2 has type 'void *' [-Wformat]
mergesort.c:87:7: warning: format '%d' expects argument of type 'int', but argument 2 has type 'void *' [-Wformat]
mergesort.c:89:7: warning: format '%c' expects argument of type 'int', but argument 2 has type 'void *' [-Wformat]

だから私がしたことは、すべての c->arr を (type *) c->arr にキャストすることでした。それから:

 * ((type *) c->arr)

基本的に、キャストされた void ポインター (これは決して null ではありません! 少なくとも私が提供した入力では常に有効な数値を指しています!) を逆参照すると、セグメンテーション違反が発生します! そのため、大量の「警告」を伴う作業出力から役に立たないセグメンテーション違反に移行したため、かなりイライラしています。

編集:

要求に応じて、データ構造の定義:

typedef struct chunk {
  void *arr;
  struct chunk *next;
  int first;
} Chunk;

これは、単一のチャンクの状態を設定し、チャンクのリンクリストを作成する方法です:

  while (index < number_of_chunks) {
    if (index == 0) {
      if ((current = malloc(sizeof(Chunk))) == NULL)
        err(EX_OSERR, "memory allocation has failed\n");
      head = current;
    }
    current->first = (chunk_size * index);
    current->arr = ((char *) array)[current->first];
    current->size = chunk_size;
    if (index != (number_of_chunks - 1)) {
      if ((current->next = malloc(sizeof(Chunk))) == NULL)
        err(EX_OSERR, "memory allocation has failed\n");
      current = current->next;
   }
  else {
    tail = current;
  }
  index += 1;
}
4

1 に答える 1

1
current->arr = ((char *) array)[current->first];

ここがあるはず&です。その値ではなく、バイトのアドレスを割り当てたいとします。arr

current->arr = &((char *) array)[current->first];

これを行うとarr、キャストと逆参照が機能するようになるはずのアドレスが含まれます。

printf("%ld\n", *(long *) c->arr);
printf("%d\n",  *(int  *) c->arr);
printf("%c\n",  *(char *) c->arr);
于 2013-08-12T22:50:24.127 に答える