2011-03-27 71 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