2016-12-16 2 views
-2

Question読んでください。ダブルポイナーを使ってディープコピーを実行するには?

以下のコードで

にターンpreOrderTraversal()で使用Stackで使用List、ルート付きツリーの、再帰を含まないが、明示的なスタックを使用して、 /* list.h */ typedefは構造体リスト{

void **array; 
    int lastItemPosition; 
    int size; 
    }List; 

    #define INITIAL_LIST_SIZE 50 

List *createList(List *list, Op opType){ 

    List *lptr = (List *)malloc(sizeof(List)); 
    void *array = NULL; 
    if(opType == CREATE_NEW_LIST){ 

    array = malloc(INITIAL_LIST_SIZE*sizeof(void*)); 
    lptr->array = &array; 
    lptr->array = memset(lptr->array, 0, INITIAL_LIST_SIZE*sizeof(void *)); 
    lptr->lastItemPosition = -1; 
    lptr->size = INITIAL_LIST_SIZE; 
    }else if(opType == DOUBLE_THE_LIST){ 

    array = malloc(2*(list->size)*sizeof(void *)); 
    lptr->array = &array; 
    lptr->array = memcpy(lptr->array, list->array, list->size*sizeof(void*)); 
    lptr->lastItemPosition = list->lastItemPosition;; 
    lptr->size = 2*(list->size); 
    }else if(opType == HALF_THE_LIST){ 

    array = malloc(((list->size)/2)*sizeof(void *)); 
    lptr->array = &array; 
    lptr->array = memcpy(lptr->array, list->array, (list->size/2)*sizeof(void *)); 
    lptr->lastItemPosition = list->lastItemPosition;; 
    lptr->size = (list->size)/2; 
    } 

    return lptr; 

} 

void insertItem(List *, void *, int); 
void *deleteItem(List *, int); 
List* createList(List *, Op); 

/* Stack.h */ 
#include"list.h" 

typedef struct Stack{ 

    List *arrayList; 
}Stack; 

void push(void *); 
void *pop(); 
void*top(); 

Wrtの、

lptr->array = memcpy(lptr->array, list->array, list->size*sizeof(void*));

memcpyは、ダブルポインタを渡している。ダブルポインタは単一ポインタへの単一ポインタなので、voidポインタが必要な関数に渡すことができます。

実際に配列をコピーする必要があるため、 void*memcpyが呼び出された場合、のような、

lptr->array = memcpy(*(lptr->array), *(list->array), list->size*sizeof(void*));

その後、

は成功し、コピー操作をmemcpy実行していますか?ディープコピーを実行するには?

+0

アレイストアを 'array'または配列**と**にコピーする必要があります。それぞれの' void * 'ポインタが指し示す内容は? – chux

+0

@chux配列とそれぞれのvoid *ポインタが指し示す内容。 Imeanディープコピー。確かに、 'void ** array = NULL'が必要でした。 – overexchange

+0

'lptr-> array [0]、lptr-> array [1]、...'が指すデータのサイズはどこですか?ディープコピーを行うには、 'array'のサイズが(' size'で)必要であるだけでなく、各 'lptr-> array [i]'が指すデータのサイズが必要です。おそらく別のフィールドですか? 'size_t * array_size'? – chux

答えて

1

既存のmemcpyステートメントは、void *という値の配列をコピーします。それらの各々はおそらく、いくつかの任意の内容で、異なるメモリブロックを指し示していると思われます。 memcpyは、その任意のコンテンツでは何もしません。ブロックのアドレスリストのコピーを作成するだけです。ブロック自体はコピーされません。

基本的なコンテンツ、ここで見ることができるコードのスニペット、それをコピーすることを含むすべてのことを、どのように行うことができるのか分かりません。これは、それぞれがvoid * 'で指されるコンテンツのタイプまたはサイズのレコードがないためです。

あなたが作った提案:

memcpy(*(lptr->array), *(list->array), list->size*sizeof(void*)) 

はいくつかの理由のために動作しません。 memcpyを最初にvoid *の値にして(それ以外の問題は1つではありません)、その最初のポインタが指している下位のメモリブロックを調べるように要求します。これは、ある量のメモリをソースからデスティネーションブロックにコピーします。しかし、新しい宛先ブロックに新しいメモリを割り当てることについて言及していないので(宛先の値を変更すると、void *自体)、ソースと宛先はおそらく同じアドレスになります。それは別の問題です。また、間違ったサイズ(問題のメモリブロックのサイズではなく、void *のリスト全体のサイズ)を使用します。それはもう一つの問題です。

達成したいと思う目標は、一回の呼び出しでは達成できません。void * s (ここではわからないコードで定義されています)は、1つの連続したメモリブロックの連続する部分を指します。この場合、単一のmemcpyが「偶然に」機能するようです。しかし、私たちが知っている限り、彼らはそのように配置されていないかもしれません。彼らは別々に割り当てられたメモリチャンクをその場所全体に割り当てているかもしれません。その場合は、ポインタの配列をループし、それぞれのブロックに対して、ブロックをコピーする前に関連するブロックのコピーのための新しい領域を挿入します。もちろん、割り当てとコピーの両方を行うには、のサイズのレコードをそれぞれブロックにする必要があります。

+0

深いコピーをする必要があります – overexchange

+0

考えています。最後のパラグラフ。 – jez

関連する問題