我這個代碼最大的問題是在這條線:
fread (buffer,sizeof(int),4000000,fp);
這條線實際上引入了一個重要的問題列表。首先,不能保證您正在閱讀的文件已成功打開。正如其他人所指出的那樣,您需要比較fp
和NULL
來作出保證。其次,似乎我經常強調這種方式:你真的應該檢查返回值。這適用於所有標準C函數,而不僅僅是fopen和fread。
返回值fread告訴您有多少項實際上被讀取。假設你要求四百萬int
秒,而該文件只包含兩個。返回值會告訴你只有兩個int
被讀取。
現在,到大的東西!讓我們首先考慮sizeof(int)
在不同的實現上有所不同。您的系統可能會讀取四個字節,而另一個可能讀取兩個字節,但可能讀取八個字節。這只是整數表示可能不同的基本方式。
讓我們考慮一個更微妙的,但同樣的破壞性方式整數表示可能會有所不同:假設你的int
s爲四個字節,用最左邊的位是最低顯著位。另一臺機器可能使用最左邊的位作爲至少的重要位。同樣,考慮字節順序排列,這是字節的順序。
假設您的int
s是32位,並且它們表示-(1 << 31)
和(1 << 31)
之間的值,這意味着沒有填充位。另一個系統可能會使用具有16位填充的32位整數,這意味着它可能僅表示-(1 << 16)
和(1 << 16)
之間的值。假設這些填充位是奇偶校驗位,以確保RAM正常運行(例如Intel Xeon服務器)。現在你有一種情況,你的服務器告訴你你的內存有問題,如果沒有。
您的代碼應該從您的文件用於存儲整數的整數表示形式顯式轉換爲計算機本機使用的任何表示形式。在將整數寫入文件時,需要確保您明確地將您的實現表示轉換爲表示表示的。同樣,當從文件中讀取整數時,代碼應該明確地將該表示轉換爲您的實現表示。例如,讓我們假設您的int
值不會超出-32767
或32767
(16位有符號整數,1的補碼)。使用兩個字節來表示這種情況是可移植的,但您需要明確定義該整數的符號和表示形式。寫入時,可以提取符號和絕對值,然後將sign * 128 + absolute_value/256
和absolute_value % 256
寫入文件。閱讀時,您會提取符號位,然後相乘並添加以重建您的值。
讓我們考慮您的文件據稱是4MB,而你正在閱讀sizeof (int) * 4000000
值。 4MB是0x400000
,而不是sizeof (int) * 4000000
。我想你真的想將沿着線的東西是什麼:
unsigned char *foo = malloc(0x400000); /* 4MB */
/* XXX: Handle malloc errors here */
assert(foo != NULL);
FILE *fp = fopen("file.bin", "rb");
/* XXX: Handle fopen errors here */
assert(fp != NULL);
size_t num_bytes_read = fread(foo, 1, 0x400000, fp);
/* XXX: Transform the bytes into integers */
free(foo);
我的問題是,它依賴於一個4MB緩存只讀取和轉換字節爲整數。這個任務根本不需要緩衝區!
FILE *fp = fopen("file.bin", "rb");
/* XXX: Handle fopen errors here */
assert(fp != NULL);
for (;;) {
int x = fgetc(fp);
/* XXX: Handle fgetc errors here */
assert(x >= 0);
int y = fgetc(fp);
/* XXX: Handle fgetc errors here */
assert(y >= 0);
/* XXX: Transform the characters in x and y into the int values */
};
free(foo);
無論你需要存儲的地方不是在問題中指定的轉化價值。如果你不需要,那麼我的下一個問題就是使用一個數組,當你只能讀一個項目,處理它,然後移動到下一個項目。
你知道平均堆棧大小是否在1到4兆字節之間?你有幾乎16兆字節的堆棧。我很驚訝你的程序甚至加載。 – 2013-04-25 08:15:31
我在C編程中是全新的,如果它可能向我展示如何完成任務,請.. – 2013-04-25 08:19:23
然後這裏有幾個其他有用的提示(與你的問題無關,但仍然很好):在C中從來沒有一個聲明函數時爲空參數列表。這意味着該函數需要一個未指定數量的未指定參數。當用於'main'時,它實際上不符合規範。如果你想要一個沒有參數的函數使用'void',如'int main(void)...'所示。你還聲明'main'返回一個'int'(這是正確的),但你實際上並沒有返回任何東西。你要麼需要調用'exit'或'return'值(零意味着沒有錯誤)。 – 2013-04-25 08:24:14