2011-03-27 27 views
3

编辑:对于我的代码片段中的错误感到抱歉,现在我看到两个输出都是相同的。以下是一个编辑版本。交换指针而不是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); 

这工作正常,但真的我的字节数组可以是V大,所以下面是我的优化我的代码的尝试。

COUPLE *titanic = (COUPLE *)data; 
printf("%s and %s", titanic->m, titanic->f); 

所以,我的问题是:

  1. (过时)为什么我得到不同的输出?
  2. (过时)如何仅通过从数组中转换来填充结构?
  3. 我应该避免这种优化吗?
  4. 它有可能的缺陷吗?
+10

重新#3:是的,通过各种手段。 – sbi 2011-03-27 20:36:46

+4

提示Re#1:考虑如何终止C风格的字符串。 – 2011-03-27 20:38:46

+2

无论什么让你觉得这是任何一种“优化”?这只是可怕的糟糕的编程,没有明显的好处来证明它的合理性。 – 2011-03-27 20:46:14

回答

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,后者可以确实使性能有潜在的巨大差异。一般而言,访问磁盘以获得更大的块的速度更快,因为它可以用于更小的块。 (虽然磁盘缓存可以缓解这一点。)

+0

地狱是的,我忘了我可以直接从文件中填充结构。非常感谢你指点我,并建议不要在不需要时进行优化。但是在你的例子中'memcpy'的意义何在? – Joulukuusi 2011-03-28 10:51:02

+0

@Angel:在我的示例中'memcpy()'的意义在于提醒您,剪切和粘贴编程确实有其不利之处。例如,你可能会留下毫无意义的代码... – sbi 2011-03-28 13:29:47

+0

我看到:D最后,我认为我的问题有一个答案,所以在此讨论这个问题,谢谢大家。 – Joulukuusi 2011-03-28 13:37:46

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

你说的是不对的。如果使用memcpy这个字符串填充一个结构,那么你的方法就不行,也不行。首先,当你这样做时

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

你正在从char数组拷贝12个字节。同时,结构不能保证是12个字节大(总大小只有11个),因此在一般情况下会导致内存溢出。其次,titanic.m中的char数组不会被零终止。 titanic.f也是如此,这就是为什么你的printf绝对没有输出"Romeo and Juliet"的变化,因为你错误地声称。

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

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

+0

对不起,我只是简化了我的真实结构,因为这里张贴太大了。用于填充结构的数据从文件中读取,没有终止字符串的零。我会编辑我的第一篇文章。谢谢。 – Joulukuusi 2011-03-27 21:07:37

+0

如果你说这些字符串在文件中不是零终止,那么这些字符串的长度是如何存储在文件中的? – Zuljin 2011-03-27 21:22:03

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个freads更快。这种或那种方式这两种解决方案都是非常不切实际的,因为这个问题是不现实的 - 谁需要存储5和6个字符长度名称的结构。

+0

是的,这不是真正的结构,我有六个结构,一个主要包含这些结构的数组(它实际上是文件内容)。非常感谢您,我认为我会坚持使用sbi的建议来阅读结构直接从文件。 – Joulukuusi 2011-03-28 11:00:21