【发布时间】:2019-10-19 23:31:55
【问题描述】:
malloc() 函数形成一个内存块(比如 20 字节类型转换为 int),那么它如何像 calloc() 函数一样用作 int 块的数组?它不应该用于在整个 20 字节(20*8 位)中仅存储一个 int 值吗?
【问题讨论】:
标签: c malloc dynamic-memory-allocation
malloc() 函数形成一个内存块(比如 20 字节类型转换为 int),那么它如何像 calloc() 函数一样用作 int 块的数组?它不应该用于在整个 20 字节(20*8 位)中仅存储一个 int 值吗?
【问题讨论】:
标签: c malloc dynamic-memory-allocation
(比如 20 个字节类型转换为 int)
不,返回的内存是一个指向 void 的指针,这是一个不完整的类型。
我们将返回的指针分配给某个类型的指针变量,我们可以使用该变量来访问内存。
引用C11,第 §7.22.3 章,内存管理功能
[....] 如果分配成功则返回的指针经过适当对齐,以便可以分配给 指向具有基本对齐要求的任何类型对象的指针,然后使用 访问分配的空间中的此类对象或此类对象的数组(直到空间 被显式释放)。 [...] 返回的指针指向 分配的空间。 [....]
由于分配的内存是连续的,指针算术可以工作,就像在数组的情况下一样,因为在数组中,元素也被放置在连续的内存中。
【讨论】:
sizeof 一个 int,您将获得 2 个字节或 4 个字节,具体取决于您的环境。但是,如果您要求 20 字节,malloc 将返回 20 字节的内存,它不知道该内存的未来使用情况。
int 变量,它是一个多个 int 变量的块。
one single int variable block- 不,不是那样的。正如我之前提到的,malloc 返回的内存不是基于任何类型的,它只是一个内存,具有定义的大小,适合对齐以分配给任何其他类型的指针 - 就是这样。
C 中有一个抽象概念,正式称为有效类型,表示存储在内存中的数据的实际类型。这是编译器在内部跟踪的内容。
C 中的大多数对象在声明变量时都有这样的有效类型,例如,如果我们输入 int a;,那么存储在 a 中的有效类型就是 int。
意味着做这样的坏事是合法的:
int a;
double* d = (double*)&a;
*(int*)d = 1;
这是可行的,因为实际内存的有效类型仍然是int,即使我们用一个非常不兼容的类型指向它。只要我们使用与有效类型相同的类型来访问它,一切都很好。如果我们使用错误的类型访问数据,就会发生非常糟糕的事情,例如程序崩溃或休眠错误。
但是当我们调用malloc 系列函数时,我们只告诉他们保留n 字节数,没有指定类型。该内存保证分配在相邻的内存单元中,但仅此而已。 malloc 和calloc 之间的唯一区别是后者将这个原始内存中的所有值设置为零。两个函数都不知道类型或数组。
返回的原始内存块没有有效类型。直到我们访问它的时候,它才会获得与访问所使用的类型相对应的有效类型。
就像前面的例子一样,我们设置哪种类型的指针指向数据并不重要。我们写int* i = malloc(n); 或bananas_t* b = malloc(n); 都没有关系,因为指向的内存还没有类型。直到我们第一次访问它时它才会得到一个。
【讨论】:
malloc 和calloc 之间的区别,calloc 实现倾向于检查溢出。此外,根据§6.3.2.3 ¶7,您的示例可能会导致 UB。否则,一个很好的答案。
从malloc返回的内存与从calloc返回的内存相比没有什么特别之处,除了calloc返回的内存块的字节被初始化为0。malloc返回的内存不必用于单个对象,也可以用于数组。
这意味着以下是等价的:
int *p1 = malloc(3 * sizeof(int));
p1[0] = 1;
p1[2] = 2;
p1[3] = 3;
...
int *p2 = calloc(3, sizeof(int));
p2[0] = 1;
p2[2] = 2;
p2[3] = 3;
两者都将返回 3 * sizeof(int) 字节的内存,可用作大小为 3 的 int 数组。
【讨论】:
malloc 返回给您的只是一个指向分配连续内存块的起始内存地址的指针。
您使用 malloc 分配的连续内存块的大小取决于您传递给 malloc 函数的参数。 http://www.cplusplus.com/reference/cstdlib/malloc/
如果您想存储int 变量,那么您可以通过将您使用的指针类型定义为int 类型来实现。
示例:
int p*; //pointer of type integer
size_t size = 20;
p = (int *) malloc(size); //returns to pointer p the memory address
在此之后,程序员可以使用指针 p 访问 int(4 字节精度)值。
calloc 与 malloc 的唯一区别是 calloc 将此内存块中的所有值初始化为零。
【讨论】: