8

「子構造体」が要素として「rusage構造体」を持つ次の2つの構造体があります。

次に、タイプ「子」の 2 つの構造体を作成します。それらを childA と childB と呼びましょう。

rusage 構造体だけを childA から childB にコピーするにはどうすればよいですか?

typedef struct{                         
        int numb;
        char *name;
        pid_t pid;
        long userT;
        long systemT;
        struct rusage usage;
}child;


typedef struct{
    struct timeval ru_utime; /* user time used */
    struct timeval ru_stime; /* system time used */
    long   ru_maxrss;        /* maximum resident set size */
    long   ru_ixrss;         /* integral shared memory size */
    long   ru_idrss;         /* integral unshared data size */
    long   ru_isrss;         /* integral unshared stack size */
    long   ru_minflt;        /* page reclaims */
    long   ru_majflt;        /* page faults */
    long   ru_nswap;         /* swaps */
    long   ru_inblock;       /* block input operations */
    long   ru_oublock;       /* block output operations */
    long   ru_msgsnd;        /* messages sent */
    long   ru_msgrcv;        /* messages received */
    long   ru_nsignals;      /* signals received */
    long   ru_nvcsw;         /* voluntary context switches */
    long   ru_nivcsw;        /* involuntary context switches */

}rusage;

私は次のようにしましたが、childA で使用法の値を変更すると、childB でも変更されるため、メモリの場所をコピーしていると思います。

memcpy(&childA,&childB, sizeof(rusage));

私はそれがchildAからのすべての値をchildBに与えることを知っています。childB の他のフィールドは既に処理済みです。必要なのは、「子」構造体にある使用法と呼ばれる rusage 構造体をコピーできることだけです。

4

7 に答える 7

21

単に:

childB.usage = childA.usage;
于 2009-09-24T23:04:27.587 に答える
10

そうではありませんか:

memcpy(&(childB.usage), &(childA.usage), sizeof(rusage))
于 2009-09-24T23:07:19.397 に答える
3

編集:わかりました、質問を読み間違えました。使用法フィールドのみをコピーしたかったのです。だから私の答えは少し無関係です。ポインターを含む構造体を割り当てたり複製したりするときに、エイリアシングの問題が発生する可能性があることを初心者に思い出させる可能性があるため、削除しません。

memcpyもちろん、他の回答の割り当ては機能します。構造体の唯一の危険は、名前へのポインターにあります。1 つの構造体を別の構造体にコピーすると、同じポインターを含み、同じメモリを指す両方の構造体が作成されます。エイリアスを作成しました。これは、割り当てられたスペースで名前を変更すると、他の構造体から見えるようになることを意味します。freeさらに、構造体を標準の無料関数に渡すと、二重になる危険があります。構造体の実際の複製を作成するには、次のようにする必要があります。

memcpy(&childA,&childB, sizeof(rusage));    
if(childB.name)
  childA.name = strdup(childB.name);

または代わりに

childA = childB;
if(childB.name)
  childA.name = strdup(childB.name);
于 2012-07-11T14:36:05.370 に答える
0

他の人が述べているように、2つの方法でそれを2つにすることができます。

1)childB.usage = childA.usage;
2)memcpy(&childB.usage、&childA.usage、sizeof(rusage));

memcpyの最初の引数は宛先、2番目の引数はソース、3番目の引数は長さ(コピーするバイト数)です。あなたが投稿したコードから、childB全体をchildAにコピーしようとしていましたが、これは本当に望まないことです。

于 2009-09-29T10:51:59.730 に答える
0

このファイルでは、最初に割り当てとstrcpyのみを使用して、origineのメンバーをdestinazioneにコピーし、次に、memcpyのみを使用してorigineをmemresにコピーします。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct inner
{
    char *parola;
    int n;
} interna;

typedef struct outer
{
    struct inner *ptr;
    int numeroesterno;
} esterna;


struct another
{
    struct inner *ptr;
    int numero;
};    //never forget ; here

int main(void)
{
    esterna *origine; //ptr to structs
    struct another *destinazione;
    struct another *memres;

    char *tmpParola;
    tmpParola = malloc(30*sizeof(char));
    strcpy(tmpParola, "AAAAA");

    interna *tmp;  //remember the TYPEDEF, and don't use struct interna
    tmp = (interna *)malloc(sizeof(struct inner));
    // if you use struct interna in sizeof you get
    //  error: invalid application of ‘sizeof’ to incomplete type ‘struct interna’ 

    tmp->n = 500;
    tmp->parola = tmpParola;

    origine = (esterna *)malloc(sizeof(struct outer));

    origine->numeroesterno = 2;
    origine->ptr = tmp;  //the data structer pointed by tmp has already been allocated and set

    // now I have the structure allocated and set, I want to copy this on destinazione
    destinazione = (struct another *)malloc(sizeof(struct another));

    destinazione->numero = origine->numeroesterno;

    //destinazione->ptr = tmp;  //in this case you don't copy struct inner, it's just a reference

    destinazione->ptr = (interna *)malloc(sizeof(struct inner));
    destinazione->ptr->parola = malloc(sizeof(char)*30);
    strcpy(destinazione->ptr->parola, origine->ptr->parola);
    destinazione->ptr->n = 111;

    //modify origine

    origine->numeroesterno = 9999;
    strcpy(origine->ptr->parola, "parola modificata in origine");

    //print destinazione

    printf("\nparola in destinazione :%s\n", destinazione->ptr->parola);
    printf("\nparola in origine :%s\n", origine->ptr->parola);

    //you can see that destinazione is a copy, because mofifying origine, destinazione deosn't change

    //now we play with memcpy

    memres = (struct another *)malloc(sizeof(struct another));

    memcpy(memres, destinazione, sizeof(destinazione)); //till here, is AAAAA
    strcpy(destinazione->ptr->parola, "parola modificata in destinazione");

    printf("\nmemcpy, numero %d\n", memres->numero);
    printf("\nmemcpy, parola :%s\n", memres->ptr->parola);

    //as you can see from the output, memcpy doesn't make a copy of destinazione:
    //modifying destinazione->ptr->parola after the assignment affects what memres carries with it
    //So from the idea that I got, memcpy just creates the pointers to the originary structure

    free(origine->ptr->parola);
    free(origine->ptr);
    return 0;
}
于 2010-05-22T17:22:06.667 に答える
0

まず、正しいコードは

memcpy(&childA,&childB, sizeof(child));

第二に、これは値をそのままコピーするため、すべての long および time 構造体に対して安全ですが、持っている char* name パラメータは同じ元の値を指します。

于 2009-09-24T23:07:59.413 に答える
0

childB.usage = childA.usage

子構造内に構造全体があるため、単純なコピーで十分です。子構造内に rusage 構造へのポインターがあった場合、それが問題になる可能性があります。その場合、childB.usage にメモリを割り当ててから memcpy を実行して、誰かが childA を変更または削除しても、childB が無傷になるようにする必要がありました。

于 2009-09-25T01:02:15.390 に答える