3

私は C を使ったプログラミングに取り組もうとしています。私の意見では、1 つの巨大で重要なステップは、生のメモリ ブロックの操作を理解し、それらを初期化し、解放することです。手元のテスト プログラムでは、それぞれがポインターを持つ 2 つの構造体を作成しました。

struct Address {
    int id;
    int var;
    char *name;
};

struct Link {
    int link_var;
    struct Address *addr;
};

この場合、name と addr はポインターです。動的にサイズを変更したいからです。

int main(int argc, char *argv[])
{    
    FILE *file = fopen("test.dat", "w");
    int i = 0;

    struct Link *link = malloc(sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10));

    struct Address addr_container[10];

    for(i = 0; i < 10; i++) {

        char temp_name[10];
        memset(temp_name, '\0', 10);

        temp_name[0] = 'A';

        struct Address addr_proto = {.id = i, .var = 10, .name = temp_name};

        addr_container[i] = addr_proto;
    }

    struct Link link_proto = {.link_var = 2, .addr = addr_container};

    memcpy(link, &link_proto, sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10));

    printf("%s\n", link->addr[4].name);



    int rc = fwrite(link, sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10), 1, file);
    if(rc != 1) printf("Failed to write database.");

    fclose(file);
    free(link);

    return 0;
}

したがって、ここで選択した方法は、*link に必要なすべてのメモリを割り当てることでした。その後、すべてのデータが初期化されたリンク構造のプロトタイプを作成しました。(また、構造体内のポインターは初期化された値を指しています)

その後、すべてのデータをスタック メモリ内のプロトタイプからヒープ上の生のメモリ ブロックにコピーします。memcpyで。

ファイルへのリンクを書き込むと、Valgrind が、初期化されていないバイトを書きたいと怒鳴ってきます。

構造内のすべてのポインターに個別にメモリを割り当てる必要があるためですか? 必要なすべてのリンクとデータを含むファイルを作成する方法がわかりません。したがって、それを読み取って、新しい空のリンク構造に再適用できます。

私は C の初心者で、これはメモリ割り当てについて学習するための初期の試みであるため、私のコードを批判するすべての回答に満足しています。また、stackoverflow で回答を検索したところ、特に構造体のポインターにメモリを割り当てる必要があるという回答が見つかりました。しかし、それをコードに実装する方法がわかりませんでした。また、構造内のファイルと必要なリンクを使用してコードをファイルに書き込むループの作成についても読みました。それが最も効率的で唯一の方法ですか?

ところで、私はポインターを使用する必要があります。最終的には、これらのポインターが char と Address 構造体配列の異なるサイズを可能にするようにしたいからです。

4

3 に答える 3

0

このコードを試すことができます:

 #include "stdio.h"

    struct Address {
        int id;
        int var;
        char *name;
    };

    struct Link {
        int link_var;
        struct Address *addr;
    };

    int main(int argc, char *argv[])
    {
        FILE *file = fopen("test.dat", "w");
        int i = 0;

        //struct Link *link = malloc(sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10));//B2 + 10B1 +100
        struct Link *link = malloc(sizeof(struct Link));
        struct Address addr_container[10];

        for(i = 0; i < 10; i++) {

            char temp_name[10];
            memset(temp_name, '\0', 10);

            temp_name[0] = 'A';

            struct Address addr_proto = {.id = i, .var = 10, .name = temp_name};

            addr_container[i] = addr_proto;
        }

        struct Link link_proto = {.link_var = 2, .addr = addr_container};

        memcpy(link, &link_proto,sizeof(struct Link));// sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10));

        printf("%s\n", link->addr[4].name);

        fprintf(file,"link_var : %d\n",(link->link_var));
        for(i = 0; i< 10; ++i)
        {
             fprintf(file,"Adress id is      :%d\n",(link->addr[i].id));
             fprintf(file,"Adress var is     :%d\n",(link->addr[i].var));
             fprintf(file,"Adress name is    :%s\n\n",(link->addr[i].name));
        }
        fclose(file);
        free(link);

        return 0;
    }

fwrite()バイナリで書き込み、すべてのデータのメモリは連続していません!

于 2013-07-24T15:27:43.653 に答える
0

達成しようとしているのはシリアル化またはマーシャリングであり、ネットワーク接続を介してデータを送信するときに一般的に行われますが、多くの場合、クロスプラットフォームである必要があるという複雑さが増します。

最近では、これを実現するためにGoogle Protocol Buffersを使用することを検討する必要があると思います。

iOS または OSX 固有のソリューションもCore Dataになる可能性があります。

基本的に、これらのポインターはファイル内では意味がなく、単一の呼び出し中のプロセスにのみ関連します。

于 2013-07-24T13:05:42.650 に答える