繁体   English   中英

交换指针而不是memcpy

[英]Swap pointers instead of memcpy

编辑 :我很抱歉我的代码片段中的错误,现在我看到两个输出都相同。 以下是经过编辑的版本。

假设我有一个结构:

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

所以,我的问题是:

  1. (已废弃)为什么我会得到不同的输出?
  2. (已废弃)如何通过从数组中强制转换来填充结构?
  3. 我应该避免这种优化吗?
  4. 它有可能存在陷阱吗?

你所说的不是真的。 如果从字符串填充结构,我使用memcpy不会也不起作用。 首先,当你这样做

memcpy(&titanic, data, sizeof(data));

你是从char数组复制12个字节。 同时,结构不保证大12字节(总大小只有11),因此一般情况下会导致内存溢出。

其次, titanic.m的char数组不会被终止。 对于titanic.f也是如此,这就是为什么你的printf完全没有改变输出"Romeo and Juliet" ,正如你错误地声称的那样。

你声称你的第一个例子“工作正常”(为什么?),而实际上第一个例子根本不起作用,即使它“有效”,它也会遇到与你的第二个例子非常相似的问题(尽管一般情况下)确切的问题是不可预测的)。

您尝试使用的方法不可行。 您无法从一个原始字符串生成一个正确形成的结构,其中包含两个字符串。 无法完成的一个明显原因是,对于两个字符串,您需要两个零终止符,而原始字符串只有一个。

  1. 因为成员从不同的位置开始。 Printf()打印一个空(\\ 0)终止的句子。
  2. 你可以这样做。 但是你需要注意类型以及如何使用它们。
  3. 如果你知道自己在做什么,那就好了。
  4. 如果你不知道你在做什么,很多陷阱......没有类型安全。

当我对你的问题发表评论时,我没有时间详细说明,所以这是试图回答的问题。 代码已经改变了,我不确定我是否会像现在这样将代码添加到代码中。

然而,使我添加该评论的根本原因仍然存在: 除非您测量并发现相关代码确实对性能产生了显着的负面影响, 否则不要尝试优化 相反,努力使您的代码尽可能可读

我非常怀疑在将数据从磁盘复制到内存后,将内存中的数据复制会对性能产生重大影响。 但是,由于您提供的代码无论如何都会对内存中的结构布局做出假设,因此直接读取结构并不会使代码的可读性降低(或者更不容易受到对该布局的更改):

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 ,后者确实可以在性能上产生潜在的巨大差异。 对于较大的块,访问磁盘以获得更大的块通常更快。 (尽管磁盘缓存可能会缓解这种情况。)

我认为唯一不涉及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字符长度名称的结构。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM