2010-01-24 37 views
2

我在C#,PHP和其他的東西轉身C++時間長了以後,我發現一些奇怪:C++的strcpy非恆定表達陣列結合

temp.name = new char[strlen(name) + strlen(r.name) + 1]; 

這個編譯

temp.name = (char *)malloc(sizeof(char[strlen(name) 
    + strlen(r.name) + 1])); 

這不(temp.name是一個char *)

編譯器錯誤是

錯誤C2540:非常量表達式 作爲數組邊界

有誰知道這個問題可能是,它會如何補救?謝謝。

+0

如果您使用C++,請忘記char數組並使用std :: string。 – 2010-01-24 17:35:09

+0

雖然程序文本看起來相同,但語義卻非常不同。 *有* C *中的數組類型,其大小爲零或運行時值。但是這些數組類型只能通過'new-type-id'來尋址。聲明數組的類型說明符不使用new-type-id,因此它們無法表示這些「奇特」類型。嘗試編寫'new(char [strlen(name)]);'或'new(char [0]);'並且注意如何用符合編譯器的方式失敗:因爲括號會使編譯器形成一個'type -id'而不是'new-type-id'。類似的,'sizeof'需要一個'type-id'。 – 2010-01-24 18:09:37

回答

6

sizeof(...)需要一個恆定的編譯時表達式。 strlen不是編譯時表達式,它是一個需要執行才能得到結果的函數。因此,編譯器不能預留足夠存儲用於聲明如下的數組:

char c[strlen("Hello")]; 

雖然字符串的長度顯然是5,編譯器不知道。

爲避免此陷阱,請勿在此處使用sizeof。相反:

char* c = (char*)malloc(strlen(name)+strlen(rname)+1); 

這給你一個指向n個字節的指針。 sizeof(char)==1始終爲真,因此緩衝區中的字節數等於您可以存儲在其中的字符數。到不同類型的malloc陣列,乘以一個陣列元件的靜態大小:

int* c = (int*) malloc(sizeof(int)*100); 

這是好的,因爲sizeof被施加到一個編譯時表達式。當然,C++的方式是更清潔:

int* c = new int[100]; 
0

的malloc需要的size_t作爲其輸入,這意味着你需要計算的實際尺寸,並通過在不是指定類型:

temp.name = (char *) malloc((strlen(name) + strlen(r.name) + 1)) * sizeof(char)); 

無論如何你應該使用new,所以我沒有看到任何真正的問題。

+0

1 == sizeof(char)總是爲真,所以你不需要乘以它。 – 2010-01-24 17:31:17

+0

我知道,但我習慣性地做它,以防我以後想要更改類型(對於寬字符類型可能?)。然後,我可以在vim中執行諸如「:s/char/wchar_t/g」之類的操作,並且所有內容都會自動修復。 :-) – 2010-01-24 17:37:38

+0

如果這是意圖,那麼最好使用'sizeof * temp.name' – 2010-01-24 17:43:54

1

問題是char[...]這是一個數組類型,在C++(和C89)數組大小需要編譯時常量。您應該使用std :: string,而不是通過new[]malloc()手動分配內存,但是如果您更願意使用手動分配,請直接將字符數計算爲字符數,而不是使用數組,然後使用sizeof來執行此操作。