c-为什么这个指针声明与malloc()一起工作



我是C的新手,有一个关于特定指针声明的问题:

这是我写的一个程序:

#include <stdlib.h>
struct n {
int x;
int y;
};

int main()
{
struct n **p = malloc(sizeof(struct n));
return 0;
}

这里的声明不正确,但为什么不正确呢?

以下是我的思考过程:

  • malloc的手册页指定它返回一个指针:
The malloc() and calloc() functions return a pointer to the
allocated memory, which is suitably aligned for any built-in
type.
  • p的类型是struct n**,也就是指向另一个指针的指针。

  • 但这个声明在理论上不应该起作用吗?因为:

  1. malloc返回类型struct n*(指针(
  2. CCD_ 6指向CCD_
  3. 所以它本质上是指向另一个指针的指针
  4. 因此满足CCD_ 8的类型

如果这是一个愚蠢的问题,我很抱歉,但我真的很困惑为什么这不起作用。感谢您提前提供的帮助。

无论如何调用,malloc的返回类型都不是struct n *malloc的返回类型为void *

使用类型为void *的值初始化struct n **对象会将其隐式转换为struct n **。这种隐式转换是允许的,因为初始化的规则遵循C 2018 6.5.16.1 1中的分配规则,该规则规定允许的分配之一为:

…左操作数具有原子、限定或非限定指针类型,并且(考虑左操作数在左值转换后的类型(一个操作数是指向对象类型的指针,另一个是指向合格或非限定版本的void的指针,并且左边指向的类型具有右边指向的类型的所有限定符;…

  1. p指向malloc返回的指针

否,值p初始化为malloc返回的值。则CCD_ 21指向所分配的存储器CCD_。

此代码为struct n分配足够的空间(使用malloc(sizeof(struct n))(,但将该空间的地址分配给struct n **,即p,这是错误的。要指向struct n,请使用struct n *p = malloc(sizeof (struct n));,或者最好使用struct n *p = malloc(sizeof *p);

要指向指向struct n的指针,请首先创建指向struct n的指针,就像上面的struct n *p = malloc(sizeof *p);一样。那么指向该指针的指针将是struct n **pp = &p;

如果您想为这些指向指针的指针分配空间,您可以使用struct n **pp = malloc(sizeof *pp);来完成,然后您可以用*pp = malloc(sizeof **pp);填充指向struct n的指针。但是,您不应该在没有充分理由的情况下添加这个额外的分配层。

请注意,MyPointer = malloc(sizeof *MyPointer);的形式通常比MyPointer = malloc(sizeof (SomeType));更可取,因为前者会自动使用MyPointer所指向的类型。后者很容易出错,例如有人错误地输入了MyPointer的类型,但没有正确设置SomeType,或者有人后来更改了MyPointer的声明,但在malloc调用中省略了对SomeType的相应更改。

这真的不起作用。在这个例子中,malloc返回一个void*,它指向堆中一个新分配的位置,这个位置足够大,可以容纳一个结构n。

请注意,malloc((返回类型void*,它基本上是指向任何潜在类型的指针,mallock((不返回类型structn*(指向您声明的结构类型的指针(。void*有一个特殊的特性,可以转换为任何其他类型的指针,然后再返回。

总之,这意味着你的代码实际上不起作用,因为结构n**的第一个解引用将是结构n,而不是结构n*。如果您尝试两次取消引用,很可能会得到无效的内存引用并崩溃。

您的代码能够在不崩溃的情况下编译和运行的原因是:

  1. 编译器自动将void*强制转换为struct n**
  2. 您永远不会尝试实际取消引用指针,这意味着您永远不会尝试无效的内存引用

简化问题并理解可能出现的问题:

int main()
{
struct n data;
struct n *pData = &data; // skipped in your version
struct n **ppData = &pData;
// struct n **ppData = &data; // Will not compile
// struct n **ppData = (struct n **)&data; // Casting but wrong!
return 0;
}

因为malloc()返回一个void ptr,所以您可以自由地将指针存储到任何指针数据类型中。如果你把它放错了数据类型。。。

相关内容

  • 没有找到相关文章

最新更新