编辑:对于我的代码段中的错误,我很抱歉,现在我看到两个输出都相同。以下是经过编辑的版本。
假设我有一个结构:
typedef struct
{
char m[5];
char f[6];
} COUPLE;
一个只包含我读入数组的短语RomeoJuliet
的文件:
char *data = malloc(11);
FILE *f = fopen("myfile", "rb");
fread(data, 1, 11, f);
fclose(f);
当我需要从字节数组填充我的结构时,我总是使用这段代码:
COUPLE titanic;
memcpy(&titanic, data, sizeof(data));
printf("%s and %s", titanic.m, titanic.f);
这很好用,但实际上我的字节数组可能非常大,所以下面是我尝试优化代码。
COUPLE *titanic = (COUPLE *)data;
printf("%s and %s", titanic->m, titanic->f);
所以,我的问题是:
答案 0 :(得分:2)
你所说的不是真的。你使用memcpy
从字符串填充结构的方法不会也不起作用。首先,当你做
memcpy(&titanic, data, sizeof(data));
您正在从char数组中复制12个字节。同时,结构不保证大12字节(总大小只有11),因此一般情况下会导致内存溢出。
其次,titanic.m
中的char数组不会被终止。对于titanic.f
也是如此,这就是为什么您的printf
绝对没有更改输出"Romeo and Juliet"
,因为您错误地声称。
你声称你的第一个例子“工作正常”(为什么?),而实际上第一个例子根本不起作用,即使它“有效”,它也会遇到与你的第二个例子非常相似的问题(虽然一般情况下,确切的问题是不可预测的。)
您尝试使用的方法不可行。您无法从一个原始字符串生成一个正确形成的结构,其中包含两个字符串。无法完成的一个明显原因是,对于两个字符串,您需要两个零终止符,而原始字符串只有一个。
答案 1 :(得分:1)
答案 2 :(得分:1)
当我对你的问题发表评论时,我没有时间详细说明,所以这是尝试回答。代码已经改变了,我不确定我是否会像现在这样将代码添加到代码中。
尽管如此,让我添加该评论的根本原因仍然存在: 除非您测量 并发现相关代码确实对性能产生了重大负面影响, 不要尝试优化 。相反,努力使您的代码 尽可能可读 。
我严重怀疑在将数据从磁盘复制到内存后,复制内存中的数据会对性能产生重大影响。但是,由于您提供的代码无论如何都会假设结构在内存中的布局,直接读取结构并不会真正使代码的可读性降低(或者更不容易受到对该布局的更改):
COUPLE titanic;
FILE *f = fopen("myfile", "rb");
fread(&titanic, sizeof(titanic), 1, f);
或者,如果你确实有一个数组,请直接读入数组:
COUPLE titanic[SIZE];
FILE *f = fopen("myfile", "rb");
fread(&titanic, sizeof(titanic), SIZE, f);
取决于SIZE
,后者确实可能在性能方面产生巨大的差异。对于较大的块,访问磁盘以获得更大的块通常更快。 (尽管磁盘缓存可能会减轻这种情况。)
答案 3 :(得分:1)
我认为唯一不涉及memcpy的解决方案是直接从文件到结构读取的解决方案。这可能是这样的
typedef struct
{
char m[6];
char f[7];
} COUPLE;
COUPLE titanic;
FILE *f = fopen("myfile", "rb");
fread(titanic.m, 1, 5, f);
titanic.m[5] = '\0';
fread(titanic.f, 1, 6, f);
titanic.f[6] = '\0';
fclose(f);
printf("%s and %s", titanic.m, titanic.f);
当然这个例子可能并不是最优的,因为我认为一次fread和几次memcpy的调用会比2次fread更快。这样或那样的解决方案都是非常不现实的,因为问题是不现实的 - 谁需要存储5和6字符长度名称的结构。