指向struct的指针,但不是实际的struct

时间:2018-02-05 20:45:53

标签: c pointers struct sizeof dynamic-allocation

我将malloc的内存分配给struct的指针,但我没有为实际的struct分配任何内容。但是,我可以访问/使用struct

typedef struct A
{
  int w;
  int x;
  int y;
  int z;
}A;

int main(void) 
{
  A* a = malloc(sizeof(A*));  //Here I allocate memory just to pointer to A

  //Why can I do this than?:
  a->z = 10;
  a->w = 456;
  return 0;
}

为什么这样做? 这只是巧合,还是总是以这种方式工作? 一些说明:

  1. 我无法使用非动态分配

  2. repl.it

  3. 中进行了测试

4 个答案:

答案 0 :(得分:2)

malloc调用分配请求的字节数并返回指针 到分配的内存块的开始。

A* a = malloc(sizeof(A*));

在这里,您要求sizeof(A*)个字节,但是您需要的字节数 请求是指向A的指针。但是你需要a的字节数 A对象,可能不一样。这似乎是一个小的差异,但它 是一个巨大的。你应该做的是:

A *a = malloc(sizeof(A));

甚至更好

A *a = malloc(sizeof *a);

第二个更好,因为你不能犯错误,它总会传递给 malloc正确的字节数。使用sizeof(<type>)很容易 错误并在不需要时添加*,就像您使用sizeof(A*)一样。

  

我无法通过非动态分配

来做到这一点

嗯,你可以。对于一个简单的结构,您可以初始化它而无需从中请求内存 堆(通过malloc):

A a;
a.z = 10;
a.w = 456;

A a = { .z = 10, .w = 456 };

也会这样做。

我们通常选择使用malloc作为结构的原因是结构 可能非常大,可能需要很多字节的内存。您拥有的空间量 变量函数的堆栈框架与之相比非常小 你在堆部分的内存。因此,从中请求内存会更好 使用malloc的堆。它还允许您将该指针传递给其他人 函数,即使在请求内存结束的函数之后也是如此。

你已经忘记了两件事:

  • 请务必检查malloc的返回,可能是NULL
  • 最后释放内存。当你不需要记忆时:

    free(a);
    

答案 1 :(得分:2)

执行此操作时:

A* a = malloc(sizeof(A*));

您没有为A的实例分配足够的内存。因此,如果您读/写任何碰巧超出实际分配范围的成员,则调用undefined behavior

对于未定义的行为,您无法准确预测节目的​​输出。它可能会崩溃,可能会输出奇怪的结果,或者(在您的情况下)它可能看起来正常工作。未定义的行为清单如何通过进行看似无关的修改(例如额外的局部变量,调用printf进行调试或使用不同的选项重新编译)来改变。

仅仅因为某个程序 崩溃并不意味着它

如果您使用valgrind之类的工具,它可以在您错误地使用内存时捕获,例如在您的示例中。

答案 2 :(得分:1)

实际上,这将取决于实际的CPU架构和操作系统,以确定它是否有效:

第一个问题是:什么是sizeof(A)什么是sizeof(A *)

我不知道任何不等式sizeof(A) <= sizeof(A *)为真的CPU,但CPU(或具有外部存储器电路的计算机)至少是可能的。

在这种情况下,您的代码将正常工作,因为malloc分配了足够的内存来保存结构A

如果没有给出这个条件,则取决于malloc的实际实施情况。许多实现将对malloc的参数进行舍入,因此malloc(5)实际上将分配16个字节,而不是5个字节。

如果malloc将分配多达sizeof(A)个字节,那么一切都很好。

如果malloc分配的sizeof(A)字节少于#include <stdio.h> extern void iplus(long *a, long *b, long *c){ printf("Starting\n"); long r= *a + *b; printf("R setup\n"); *c=r; printf("Done\n"); } ,则取决于是否使用分配内存后的内存以及是否存在的问题:

如果分配的内存之后的内存不存在(例如,在使用MMU时未映射),则会出现错误,具体取决于系统 - 在大多数现代计算机上都会出现“异常”,程序将崩溃。

如果该内存之后的内存被其他一些数据占用,您将覆盖该数据,这可能会导致错误。

如果该存储器之后的存储器存在但未使用,则程序将正常工作。

答案 3 :(得分:0)

没有人说你应该做什么。这样做:

int main(void) 
{
  A* a = malloc(sizeof(A));  // Here I allocate an ins6tance of A and set a pointer to it

  a->z = 10;
  a->w = 456;
  return 0;
}