[英]Dynamically allocating array with the [] operator instead of using malloc?
我確信這已經被問了一百萬次,但我找不到解釋它的答案。 有人告訴我永遠不要這樣做,但我真的不明白為什么。 為什么這樣的事情不能算作動態分配 memory ,為什么那么糟糕?
int a;
scanf("%d",&a);
int arr[a];
這不是動態分配,而是可變長度數組。
這種數組的生命周期是它封閉的 scope,就像一個固定大小的數組,所以你不需要擔心釋放。 這些 arrays 通常駐留在堆棧中,因此堆棧的大小確實限制了 VLA(或任何陣列)的大小。
如果您發現 VLA 對於堆棧來說太大,您可以隨時退回到使用malloc
。
使用 [] 運算符而不是使用 malloc 動態分配數組?
這里的[]
用於定義一個數組。 []
這里,不是運算符。
int arr[a];
有人告訴我永遠不要這樣做,但我真的不明白為什么。
這個咒語適用於C(和生活)中的許多東西,在您了解如何使用之前不要使用它。
為什么這樣的事情不能算作動態分配 memory
它動態分配 memory 分配,但通常使用不同的 memory 池並且具有與通過malloc()
不同的生命周期。
......為什么它那么糟糕?
int arr[a];
是一個可變長度數組(VLA),存在以下問題:
並非總是可用。 VLA 在 C99 中支持,並且在以后的版本中經常(但並非總是)支持。 研究__STDC_NO_VLA__
。
使用int a
,當a <= 0
時,代碼是未定義的行為 (UB)。
當a
太大時,沒有標准機制來檢測 memory 不足。
VLA 更好地用於受控的較小尺寸的情況。
首先,讓我告訴您,這稱為變長數組,它是一個可選功能。 最好不要依賴此功能(或編譯器支持)。
另一方面,分配器函數( malloc()
、 free()
和 family)符合標准,任何符合標准的編譯器/庫都將支持這些函數。
也就是說,其他答案中提到了差異,主要差異在於 scope 和便攜性。
為什么這樣的事情不能算作動態分配 memory
在運行時確定 object 的大小不足以進行動態分配。 動態分配需要直接或間接使用專門執行動態 memory 分配的函數之一,其中malloc
、 calloc
和realloc
是主要示例。 你的例子...
int arr[a];
...不這樣做,所以 object 不是動態分配的。 你arr
是一個或多或少的普通局部變量,具有可變長度數組類型。
從語義上講,動態分配的對象具有“已分配”的存儲持續時間,這意味着它們存在並保留其最后存儲的值,直到顯式釋放。 相反,您的arr
具有“自動”存儲持續時間,這意味着當其最內層包含塊的執行終止時它不再存在。
為什么那么糟糕?
意見不一。 VLA 在 C99 中是必需的功能,但在 C11 中支持是可選的。 如果您在代碼中使用 VLA,那么您會限制其可移植性。 C++ 不支持它們(或者至少不支持——我知道它們現在也將使用 C++,也許它們已經到了),這對某些人來說可能是個問題。
但是,引用的主要風險是 VLA 的通常和自然實現是在堆棧上分配它們,並且堆棧大小通常比堆空間更有限。 在像您這樣的幼稚示例中,很容易創建堆棧溢出,這可能取決於用戶輸入,因此既難以測試又存在潛在的安全風險。
我確實不時在我的代碼中使用 VLA,但通常以不受上述堆棧破壞風險影響的方式使用。 我通常對“永遠不要那樣做”的告誡持懷疑態度,但實際上我永遠不會編寫您為生產應用程序提供的確切代碼。
這是一個可變長度數組的例子。 它的生命周期與任何其他auto
變量(包括固定長度數組)相同,因此一旦退出其封閉的 scope,它的 memory 將被釋放。
與固定長度的 arrays 不同,VLA 不能在文件 scope(在任何函數之外)或使用static
關鍵字聲明,也不能使用初始化程序聲明。 由於它們通常是如何管理的,它們不能任意大。 盡管有名稱,但一旦定義它們就無法調整大小 - 可變長度的“變量”僅意味着它們的大小在每次定義時都可以不同。
VLA 有用但有限。 當您需要一些 function 本地的臨時工作存儲並且不需要太大(不超過 1 兆字節左右)時,它們非常有用。
它們僅在 C99 中引入,在 C11 中成為可選,因此對它們的支持可能有點參差不齊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.