2014-03-12 52 views
1

我的座右銘是以最小的系統負載將一些虛擬數據寫入文件。數據的大小在運行時是未知的並且已被指定。C中可變大小的數組可以嗎?

爲此,我可以考慮2種解決方案。

1)使用動態存儲器分配

reserve_size_in_file (int reserve_size, FILE *fp) 
{ 
    char *p 
    p = malloc(reserve_size) 
    fwrite(p, sizeof(*p), 1, fp); 
    free(p); 
} 

2)使用陣列

reserve_size_in_file (int reserve_size, FILE *fp) 
{ 
    char arr[reserve_size]; 
    fwrite(arr, sizeof(arr), 1, fp); 
} 

我認爲第二種方法將不會如聲明具有可變長度(EWWW ...)的陣列工作,我認爲是不允許的。但它正在工作。現在我的問題是,是否可以像這樣使用它?另外,如果還有其他更好的方法可以做到這一點,請提出建議。

注意:我不能使用fallocate(),因爲我只能處理流IO。

編輯:

我剛看到,我可以使用的fileno(FP),並使用fallocate()。但我看不到許多使用fallocate()的應用程序。是否有使用fallocate()

防爆任何顧慮:fallocate(fileno(fp), 0, 0, 100000);

+0

在選項1中,您正在泄漏內存。你需要''用'malloc()'分配你已經分配的內存。 –

+0

@GrahamBorland已更新。謝謝。 –

+0

它是否真的需要消耗大量的存儲空間,或者是一個可接受的稀疏文件? – datenwolf

回答

2

我會做這樣的:

reserve_size_in_file (int reserve_size, FILE *fp) 
{ 
    /* Usual HDDs have a block size of 512, but big 
    * block storage is becoming popular. */ 
    char arr[4096]; 

    /* initialize to 0xff, since runs of NUL bytes might 
    * be transparently replaced with sparse file holes. */ 
    memset(arr, 0xff, sizeof(arr)); 

    while(reserve_size > sizeof(arr)) { 
     fwrite(arr, sizeof(arr), 1, fp); 
     reserve_size -= sizeof(arr); 
    } 
    fwrite(arr, reserve_size, 1, fp); 
} 

這完全避免了動態內存分配和運行很好用的塊大小的工作。

+0

+1隨着演變的問題這個答案可能是更好的一個。 –

+0

謝謝。我希望接受這個答案。但是,請您評論fallocate()部分嗎? –

+0

@Manty:'fallocate',或者如果你想保持便攜性'posix_fallocate'基本上和我的代碼片段一樣,但是在「幕後」並且沒有輔助緩衝區。大多數應用程序不使用fallocate,但對它們沒有用處。事實上,實際上只有極少數情況下需要在存儲設備上預先分配空間。事實上,對於我來說,只有兩個人想起來了:*實時視頻錄製*和*數據庫存儲集羣*,甚至數據庫對預分配的使用也很少。所以這裏有一個問題:爲什麼你認爲預分配是必需的? – datenwolf

3

Variable length arraysVLA)是C99的標準功能,並都OK,只要你知道你將使用支持C99編譯器使用。 C11標準雖然使可變長度數組可選。即使在C99模式之外,gccclang都支持VLA作爲擴展。另一方面,Visual Studio直到最近才支持C99,我不認爲他們支持VLA。

如果您事先不知道大小,可以通過malloc進行動態內存分配。

正如Jens指出的那樣,VLA確實在堆棧上,如果數組的大小很大,可能會出現問題,如果是這種情況,那麼您將不得不使用動態內存。

+0

我剛剛編輯了我的問題。你能否就此解釋一下。謝謝。 –

1

VLA有兩個缺點

  • 你不知道你有多少數據保留他們
  • 「在堆棧上」沒有錯誤返回如果分配沒有成功。

所以除非你確定你的數組永遠不會超出一千公里的數據,否則我不會爲此選擇它們。否則,如果分配失敗,你會因爲計算器而產生虛假錯誤。

+0

謝謝。除了上述2以外的其他選項?我還能想到的另一個方面是每次開始時在for循環中寫入1個字節。這是一般的標準方式嗎? –

+0

對此沒有真正的標準。許多人做的事情是保留一個固定大小的數組,例如8k,然後迭代它。 –

+0

我剛剛編輯了我的問題。你能否就此解釋一下。謝謝。 –