在一些内存分配中,我发现了这一点。但我不明白。
char * mem_alloc()
{
char *point;
char *a;
point = (char *)malloc(block_num);
a = *(char**) point;
return a;
}
在一些内存分配中,我发现了这一点。但我不明白。
char * mem_alloc()
{
char *point;
char *a;
point = (char *)malloc(block_num);
a = *(char**) point;
return a;
}
char * mem_alloc()
以我的经验,返回指针的函数几乎总是程序设计有缺陷的标志。这样的指针可以指向以下内容:
在这种情况下,它指向动态内存,因此我们可能会假设程序设计不佳并且可能存在内存泄漏。
point = (char *)malloc(block_num);
这段代码意味着编写它的人对 malloc 的工作方式和 void 指针的工作方式感到困惑。malloc 的结果不应该进行类型转换,请参见this和this。类型转换的冲动意味着程序员对 C 语言感到困惑,和/或他们试图在 C++ 编译器上编译 C 代码。
“block_num”是可疑的,如果这是一个全局的、非常量的变量,那么程序设计很差。
a = *(char**) point;
这意味着,获取指向堆上未初始化内存的点的地址,然后假设该点是一个指向指针的指针,从而将堆的垃圾内容视为指针。然后将该指针返回给调用者,该指针指向 la-la 土地中的一个随机位置。在这样做的同时,会造成内存泄漏。
这似乎设置了一个指向点的值(这是一个地址)。
a = *(char**) point;
上面的语句是类型转换指向 - `(char**) point' 部分中的“pointer to a pointer”。在此之后,您将 * 用于取消引用,将其更改
为(指向指针的指针)
=> 指针的值。
因此,存储在 point 中的值(而不是地址)被复制到 a 中。
我仍然不确定为什么要编写这种代码。
您发布的代码很愚蠢-您确定它是完整的吗?
“point”和“a”都是指针。
"a" 被初始化为 "point" ...但 "point" 完全是uninitialized。如果调用者试图使用返回值“a”,就会发生不好的事情。
这是另一个例子:
struct Point {
int x;
int y;
};
...
char * mem_alloc (int size)
{
return (char *)malloc (size);
}
...
Point *my_point = (Point *)mem_alloc (sizeof (struct Point));
...
这个片段也很愚蠢......但希望它说明了你正在查看的代码背后的一些基本原理......
a
包含存储在 指向的位置的值point
。由于point
未初始化,它指向一个包含随机值的随机位置,因此现在a
指向它开始的随机值。
所以代码是无操作的。
如果你看 的概念malloc
,它总是返回分配的内存空间的基地址,malloc
函数的实际语法是语法:
pointer_to_store_base_add_of_mem = (data_type_of_allocated_memory)malloc(size_of_array)
在上面的示例中,您已经分配了内存的字符类型,因此您使用了 (char*),并且在 block_num 中您已经给出了字符数组的大小,并且点指针存储了分配内存的基地址。
查看在 Lundin 的回答的评论中发布的代码 chenyoufu123:
ptr = (char *)malloc(block_num * size);
for(k=0; k<block_num-1; k++) {
*((char **)(ptr + k*size)) = ptr + (k+1) * size;
}
*((char **)(ptr + k*size)) = NULL;
那仍然是糟糕的代码,但与问题中的原始代码相比并非完全没有意义。特别是与它用于从另一个评论创建链接列表的注释一起。
情况是——假设代码是“正确的”——你有一个
struct Node
{
struct Node *next;
/* More members */
};
和size_t size = sizeof(struct Node);
(名称可能会有所不同)。然后
ptr = (char *)malloc(block_num * size);
block_num
为连续struct Node
的 s分配内存。人们通常会将其分配为
struct Node *ptr = malloc(block_num * sizeof *ptr);
循环
for(k=0; k<block_num-1; k++) {
*((char **)(ptr + k*size)) = ptr + (k+1) * size;
}
*((char **)(ptr + k*size)) = NULL;
k * sizeof(struct Node)
然后将内存块开头后面的地址重新解释ptr + k*size
为指向指针的指针(a char**
,但在当今的大多数 PC 体系结构中,这并不重要,因为所有对象指针都具有相同的表示形式 - 如果它很重要,则代码被破坏无论如何)并将下一个sizeof(struct Node)
大小的内存块的地址写入该位置。由于next
指针是 的第一个成员,因此将列表中struct Node
下一个的地址写入当前的指针。最后,最后的指针设置为。struct Node
next
struct Node
next
struct Node
NULL
通常的写法,
struct Node *ptr = malloc(block_num * sizeof *ptr);
int k;
for(k = 0; k < block_um - 1; ++k)
{
ptr[k].next = &ptr[k+1]; // or ptr + (k+1), if you prefer
}
ptr[block_num-1].next = NULL;
不仅更清晰,它还具有在具有不同大小或表示的平台char*
上工作的优势。struct Node*