包含指向 void 指针的指针变量的 memcpy 结构

memcpy struct containing pointer variables to void pointer

我喜欢这个结构

struct free_bitmap{
   int *node_bitmap;
   int *data_bitmap;
}

我想将此结构复制到固定内存块并使用二进制模式写入文件并将此数据从文件读取到固定内存block.And而不是使用 memcpy 将此数据复制到结构。

像这样

struct free_bitmap f1;
struct free_bitmap f2;

f1.node_bitmap = (int *) malloc( sizeof(int) * 20 );
f1.data_bitmap = (int *) malloc( sizeof(int) * 128);

void * fblock = (void *) malloc(256);
memcpy((char*)fblock,(void*) &f1 ,256 );
int fd = open("test",O_RDWR|O_CREAT, 0600);
write(fd,fblock,256);
free(fblock);

我可以这样写数据,但我不确定 memcpy 是否正在复制我的指针variables.And我读取了文件但不起作用。

 block = (void *) malloc(256);

lseek(fd, 0, SEEK_SET);
read(fd,fblock,256);

f2.node_bitmap = (int *) malloc( sizeof(int) * 20 );
f2.data_bitmap = (int *) malloc( sizeof(int) * 128);

memcpy((void*) &f2 , (char*)fblock , 256 ); 
free(fblock);

for(i=0;20>i;++i)
    printf("%d " ,f1.node_bitmap[i]);

free(f2.node_bitmap);
free(f2.data_bitmap);

我的完整代码在这里Click

memcpy((char*)fblock,(void*) &f1 ,256 );

似乎 memcpy 使您的代码失败。如果你想复制包含指针(或数组)的结构,你应该为这个结构的每个参数使用 memcpy。例如,如果你想复制 256 字节的结构来解决指针 fblock 指向:

memcpy(fblock,f1.node_bitmap ,20*sizeof(int));
// then copy the `256-20*sizeof(int)` by of `f1.data_bitmap` to `fblock`
memcpy(((uint8_t *))fblock + 20*sizeof(int),f1.data_bitmap ,256-20*sizeof(int));
// Note that, you should initialize the data in f1.data_bitmap before copying

如果要将f1.data_bitmapf1.node_bitmap中的所有数据复制到fblock,则必须至少为该指针分配128*sizeof(int) + 20 * sizeof(int)字节。

复制数据到f2 struct:

时类似
memcpy((void*) &f2 , (char*)fblock , 256 ); 

您可以更改为:

memcpy(f2.node_bitmap, fblock, 20*sizeof(int));
memcpy(f2.data_bitmap, (uint8_t *)fblock + 20*sizeof(int), 256 - 20 *sizeof(int));

您可以查看有关复制结构的更多信息:Copying one structure to another

另一件事,你不应该转换 malloc 函数:Do I cast the result of malloc?

如果代码像memcpy(fblock,f1.node_bitmap ,20*sizeof(int));,你不需要转换源指针和目标指针,因为memcpy不关心数据类型,它关心源地址,地址目的地和您要复制的数据量。

I want to copy this struct to fixed memory block and write to file with binary mode and read this data from file to fixed memory block.And than copy this data with memcpy to struct.

您真的不需要创建中间缓冲区。只需 read/write 直接到结构。您可以通过对每个 "save/restore" 操作进行 两次 读取或写入来执行此操作。这有时称为 "serialization"

它更简单、更快速而且不需要memcpy

这是为执行此操作而重构的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

enum {
    NODECOUNT = 20,
    DATACOUNT = 128,
};

struct free_bitmap {
    int *node_bitmap;
    int *data_bitmap;
};

void
bitmap_alloc(struct free_bitmap *f)
{

    f->node_bitmap = malloc(sizeof(int) * NODECOUNT);
    f->data_bitmap = malloc(sizeof(int) * DATACOUNT);
}

void
bitmap_free(struct free_bitmap *f)
{

    free(f->node_bitmap);
    free(f->data_bitmap);
}

void
bitmap_write(int fd,struct free_bitmap *f)
{

    write(fd,f->node_bitmap,sizeof(int) * NODECOUNT);
    write(fd,f->data_bitmap,sizeof(int) * DATACOUNT);
}

void
bitmap_read(int fd,struct free_bitmap *f)
{

    read(fd,f->node_bitmap,sizeof(int) * NODECOUNT);
    read(fd,f->data_bitmap,sizeof(int) * DATACOUNT);
}

int
main()
{
    struct free_bitmap f1;
    struct free_bitmap f2;

    bitmap_alloc(&f1);

    int i;

    for (i = 0; i < NODECOUNT; ++i)
        f1.node_bitmap[i] = i;

    int fd = open("test", O_RDWR | O_CREAT, 0600);

    bitmap_write(fd,&f1);

    printf("a");
    lseek(fd, 0, SEEK_SET);

    bitmap_alloc(&f2);
    bitmap_read(fd,&f2);

    for (i = 0; i < NODECOUNT; ++i)
        printf("%d ", f1.node_bitmap[i]);
    printf("\n");

    bitmap_free(&f1);
    bitmap_free(&f2);

    return 0;
}

更新:

I mean I want to use this file like a file system. For example Write this struct to first block and another struct to second block and Block size 2kb.So I use the heap memory to fix data lenght.File size fixed and 1Mb for example

好吧,这里有一个版本,写入多个块并比较结果。它将每个对齐到 2KB 的块大小,使用 1MB 的总大小:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

enum {
    NODECOUNT = 20,
    DATACOUNT = 128,
    BLOCKSIZE = 2 * 1024,
    FILESIZE = 1024 * 1024,
    NMAP = 5,
};

struct free_bitmap {
    int *node_bitmap;
    int *data_bitmap;
};

void
bitmap_alloc(struct free_bitmap *f)
{

    f->node_bitmap = malloc(sizeof(int) * NODECOUNT);
    f->data_bitmap = malloc(sizeof(int) * DATACOUNT);
}

void
bitmap_free(struct free_bitmap *f)
{

    free(f->node_bitmap);
    free(f->data_bitmap);
}

void
bitmap_write(int fd,struct free_bitmap *f)
{
    ssize_t tot = 0;

    tot += write(fd,f->node_bitmap,sizeof(int) * NODECOUNT);
    tot += write(fd,f->data_bitmap,sizeof(int) * DATACOUNT);

    tot = BLOCKSIZE - tot;
    if (tot > 0)
        lseek(fd,tot,SEEK_CUR);
}

void
bitmap_read(int fd,struct free_bitmap *f)
{
    ssize_t tot = 0;

    tot += read(fd,f->node_bitmap,sizeof(int) * NODECOUNT);
    tot += read(fd,f->data_bitmap,sizeof(int) * DATACOUNT);

    tot = BLOCKSIZE - tot;
    if (tot > 0)
        lseek(fd,tot,SEEK_CUR);
}

int
mapcmp(int mapidx,const char *tag,const int *lhs,const int *rhs,int count)
{
    int i;
    int bad = 0;

    for (i = 0;  i < count;  ++i) {
        if (lhs[i] != rhs[i]) {
            printf("mapcmp: MISMATCH mapidx=%d tag=%s i=%d lhs=%d rhs=%d\n",
                mapidx,tag,i,lhs,rhs);
            bad = 1;
        }
    }

    return bad;
}

int
main(void)
{
    struct free_bitmap wlist[NMAP];
    struct free_bitmap *wcur;
    struct free_bitmap rlist[NMAP];
    struct free_bitmap *rcur;
    int off;
    int i;
    int mapidx;
    int code;

    int fd = open("test", O_RDWR | O_CREAT, 0600);
    ftruncate(fd,FILESIZE);

    // create blocks with unique test data
    off = 0;
    for (wcur = &wlist[0];  wcur < &wlist[NMAP];  ++wcur, off += 23) {
        bitmap_alloc(wcur);

        for (i = 0; i < NODECOUNT; ++i)
            wcur->node_bitmap[i] = i + off;

        for (i = 0; i < DATACOUNT; ++i)
            wcur->data_bitmap[i] = i + off + 17;

        bitmap_write(fd,wcur);
    }

    lseek(fd, 0, SEEK_SET);

    for (rcur = &rlist[0];  rcur < &rlist[NMAP];  ++rcur) {
        bitmap_alloc(rcur);
        bitmap_read(fd,rcur);
    }

    code = 0;

    // compare all data in all blocks
    for (mapidx = 0;  mapidx < NMAP;  ++mapidx) {
        wcur = &wlist[mapidx];
        rcur = &rlist[mapidx];

        if (mapcmp(mapidx,"NODE",rcur->node_bitmap,wcur->node_bitmap,NODECOUNT))
            code = 1;

        if (mapcmp(mapidx,"DATA",rcur->data_bitmap,wcur->data_bitmap,DATACOUNT))
            code = 1;
    }

    // release all blocks
    for (mapidx = 0;  mapidx < NMAP;  ++mapidx) {
        bitmap_free(&wlist[mapidx]);
        bitmap_free(&rlist[mapidx]);
    }

    printf("%s\n",code ? "FAIL" : "PASS");

    return code;
}