【发布时间】:2021-11-26 04:33:27
【问题描述】:
当我们使用malloc 时,它返回一个指针,指向传递给malloc 的固定大小内存地址的开头。例如,malloc(40) 会抛出一些 40 字节长的未初始化内存。问题是,我已经看到人们对这段内存进行索引的代码示例。我的问题是,malloc 如何定义索引的大小?
以这段代码为例,
#include <stdio.h>
#include <stdlib.h>
int main()
{
char **array;
array = malloc(3 * sizeof(char *));
for (int i=0; i < 3; i++) {
array[i] = malloc(10);
}
for (int i=0; i<10; i++) {
free(array[i]);
}
free(array);
return 0;
}
我首先想解释一下我认为正在发生的事情,并希望有人能纠正我的任何错误想法。
char **array 创建变量“array”,它将成为一个指向字符指针的指针。这意味着,如果我们取消引用该值,它将为我们提供存储 char 的内存地址位置。
array = malloc(3 * sizeof(char *)) 。让我们在这里假设sizeof(char *) 将始终返回 8。继续下去,这将创建一个 32 字节长的未初始化内存。他们这里的关键点是它是 32 字节长,它如何处理可索引的大小?
array[i] = malloc(10) 是我在这里感到困惑的一部分。我们有一块 32 字节长的未初始化内存,我们如何索引它?
我有一个想法想提一下,希望有人能纠正我的任何误解。
0x02 0x0A 0x12
[ 0x90 | 0x91 | 0x92 ]
<-- sizeof(char*) -> <-- sizeof(char*) -> <-- sizeof(char*) ->
^
|
|
0x01 (memory address of variable array) (array - points to 0x02)
-- Random memory locations
0x90 -- | Starting from the memory address location 0x90, the next sizeof(char) bytes will representing the value in this memory address location.
['c']
0x91
['a']
0x92
['t']
根据我的理解,malloc 将知道我们对初始指针所做的转换的可索引大小,即char** array 内部的char*。这意味着,我们从malloc(40) 返回的指针将指向,在本例中,位于0x02(数组的开头)的内存地址空间。
每次我们执行array[i] 操作时,我们实际上是在执行0x02 + sizeof(char*) * i,这会将指针推到新位置的开头。这意味着例如,当我们执行array[1] 时,我们实际上正在执行0x02 + sizeof(char*) * 1,这会将我们推向0x02 + 8 (0x0A)。这意味着从内存地址位置0x0A 开始,下一个sizeof(char *) 字节将作为索引 存储在内存中的这个位置。在这个例子中它是一个char *,在我的例子中我写了0x90,这意味着内存中的某个其他位置0x90下一个sizeof(char),即1个字节将具有实际值。表示“c”的实际值(例如),但这可能位于内存中的其他位置,与 malloc 无关。
使用这个公式,我们可以得到一个从 malloc 返回的整数数组,例如 int* ten_int_array = malloc(10 *sizeof(10))。现在公式将调整为ten_int_array + sizeof(int) * i。这将使 malloc 不是固定大小的可索引。
感谢您的任何回复,我正在尝试在这里验证我的假设。
【问题讨论】:
-
与
malloc无关。进行索引的不是malloc。它是编译器。当代码进行索引时,编译器将根据指针的类型生成正确的偏移量。malloc所做的只是分配您告诉它的内存大小(可能更多用于簿记和对齐)。所以不完全清楚你的问题是什么。 -
当你有一个
T *并从中索引时,你访问内存位置就好像它包含T的连续元素数组一样。 -
指针的大小并不重要。指针只是一个内存地址。重要的是编译器在计算数组的偏移量时会做什么。它通过将数组索引乘以数组的元素大小来做到这一点。结果数字是从存储在指针中的内存地址到数组中的索引元素的偏移量(以字节为单位)。
-
所有 malloc 所做的就是分配一块您请求的大小的内存块,然后将内存地址返回到该块的第一个字节。
-
阅读这些 cmets,如果我要在一个公式中将其隔开,它将是
T* example = malloc(10 * sizeof(T)),那么T[i]实际上就是example + sizeof(T) * i。