我已经看到了在C99中使用以下表达式分配2D数组的各种建议:
int (*array)[cols] = malloc(rows * sizeof *array);
我想知道三件事:
是否在堆上分配了整个结构?或者这实际上是一堆指针(在堆栈上)指向堆上的数组..?
分配的内存是否完全连续?
是否只需要一次调用free(array)
来释放整个2D结构?我在某个地方看过这个 - 不记得在哪里 - 它似乎对我有用,但我想了解原因。
答案 0 :(得分:8)
(1)整个结构是否在堆上分配?或者这实际上是一堆指针(在堆栈上)指向堆上的数组..?
整个结构(malloc分配的所有内容)都在堆上。
(2)分配的内存是否完全连续?
是的,override func viewDidLoad() {
super.viewDidLoad()
getJSON { (usdPrice) -> Void in
// do something with usdPrice
print(usdPrice)
}
}
func getJSON(completion: (Double) -> Void) {
let url = NSURL(string: baseURL)
let request = NSURLRequest(URL: url!)
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error == nil{
let swiftyJSON = JSON(data: data!)
let usdPrice = swiftyJSON["bpi"]["USD"]["rate"].doubleValue
completion(usdPrice)
} else {
print("There was an error!")
}
}
分配一个连续的存储区域。
(3)是否只需要一个调用free(array)来释放整个2D结构?我在某个地方看过这个 - 记不清楚 - 它似乎对我有用,但我想了解原因。
是的,这是真的。至于为什么,它为什么会以其他方式?您使用malloc
分配单个存储区域,malloc
用于取消分配先前free
返回的单个存储区域。
我怀疑你对声明类型感到困惑,尽管你没有提到它:
malloc
这意味着int (*array)[cols]
变量成为单个指针(它本身在堆栈上分配)到一个带有array
元素的int
数组(在其上分配)堆由于使用cols
)。将此与更常见的比较:
malloc
...而是声明一个指针的一维数组(其中数组本身将在堆栈上)。您可以使用后者创建一个指向数组的数组,方法是在每个元素中存储指向一系列数组的指针(您确实必须单独分配和释放这些数组!)。这种结构可以与2D数组类似的方式使用,但实际上不是一回事。
还要记住C中的指针始终指向数组。因此,即使第一个声明声明了一个指向一维数组的指针,它也可以用来指向数组这样的数组,即你想要的二维数组。实际上,int *array[cols]
调用为这样的数组分配了存储空间:
malloc
这里,malloc(rows * sizeof *array);
是具有sizeof *array
元素的(单个)1D数组的大小(以字节为单位)。当乘以行数时,它会产生大小为cols
×rows
的二维数组的存储要求。
答案 1 :(得分:2)
C不进行隐藏内存分配。问题中的类型可以用作真正的2D数组。实际上它是指向cols
"的数组[int
]的指针。
OTOH,类似int *array[cols]
(注意缺少的括号)不是2D数组,而是指向int
"的指针数组。然而,即使在这里,您也必须明确malloc
数组和每一行!
对于每个malloc
,您需要相应的free
。
请注意,C标准不需要堆,堆栈或任何其他特定的管理结构。这留给实施。但是,大多数托管环境(即完整大小的运行时)使用类似堆的东西。
请记住检查malloc
的结果并正确处理分配失败。