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

问题描述 投票:1回答:2

我喜欢这个结构

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

我想将此结构复制到固定存储块并以二进制模式写入文件,然后从文件中读取此数据到固定存储块。而不是使用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正在复制我的指针变量。并且我读取了文件,但是不起作用。

 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

c pointers struct memcpy
2个回答
1
投票
memcpy((char*)fblock,(void*) &f1 ,256 );

似乎memcpy使您的代码失败。如果要复制该内容指针(或数组)的结构,则应为此结构的每个参数使用memcpy。例如,如果要复制256个字节的struct到指针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结构时类似:

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));

您可以查看复制struct的更多信息:Copying one structure to another

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

如果代码喜欢memcpy(fblock,f1.node_bitmap ,20*sizeof(int));,则不需要强制转换源指针和目标指针,因为memcpy不在乎数据类型,它在乎源地址,目标地址和数据量您要复制的内容。


0
投票

我想将此结构复制到固定存储块并以二进制模式写入文件,然后从文件中读取此数据到固定存储块。而不是使用memcpy复制该数据到结构。

您确实不需要创建中间缓冲区。只需直接读取/写入该结构即可。您可以通过对每个“保存/还原”操作进行two读取或写入操作来完成此操作。有时称为“序列化”

它更简单,更快捷,不需要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;
}

UPDATE:

我是说我想像文件系统一样使用此文件。例如,将此结构写入第一个块,将另一个结构写入第二个块,块大小为2kb。因此,我使用堆内存来修复数据长度。文件大小固定为1Mb,例如]

好,这是一个编写multiple块并比较结果的版本。它将每个对齐为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;
}
© www.soinside.com 2019 - 2024. All rights reserved.