在一个函数中分配内存并在另一个函数中使用它

时间:2016-06-18 06:45:32

标签: c reference dereference

以下代码似乎有效。 linux上的gcc 5.2.1没有给出任何警告。

我是C的新手。我通过写下&和*运算符在每一行都有英文句子和反复试验。

有两件事我不确定。

A行中p0的初始值是不可预测的。然而,E行将值赋给main中变量p0的值指定的地址。这会导致任何问题吗?如果是这样,如何解决?

代码使用了很多*,就像C行中的***一样。如果没有收到gcc的警告,可以使用更少的*吗?

谢谢。

#include <stdlib.h>
#include <stdio.h>

void* f(int*** ptr_p)     //C
{
    int** p = *(ptr_p);   //D
    *p      = malloc(8);  //E
    *(*p)   = 200;        //F
    (*p)[1] = 4;          //G
}

int main(void)
{
    int** p0;             //A
    f(&p0);               //B
    printf("%d, %d\n",*(*p0), (*p0)[1]);
    free(*p0);            //H
}

如果你想看英文句子,这里就是。

警告:我是C的新手,我不知道他们是否都是正确的。

行[A] int** p0;

p0的值无法预测。

行[B] f(&p0);

&p0是变量p0的地址。 f(&p0)表示调用函数f并将&p0分配给函数的第一个参数。

行[C] void* f(int*** ptr_p)

B行将&p0分配给ptr_p。这意味着ptr_p的值现在等于main函数中变量p0的地址。

行[D] int** p = *(ptr_p);

*(ptr_p)表示由ptr_p的值指定的地址处的值,被解释为地址。 ptr_p的值是main函数中变量p0的地址,如行C中所述。因此,*(ptr_p)是main函数中变量p0的值。

p = *(ptr_p);表示将主函数中p0的值指定为p

的值

行[E] *(p) = malloc(8);

*(p)表示由p的值指定的地址处的值。 p的值是main中p0变量的值,如行[D]中所述。然后,*(p)表示p0main()变量的值指定的地址值。

malloc(8)在内存中保留8个字节,并返回8个字节中第一个的地址。

整行表示将这8个字节中第一个的地址指定为p0main()变量指定的地址值。

行[F] *(*p) = 200;

行[G] (*p)[1] = 4;

(p)[1]表示*(p + 1)

(*p)[1]表示*(*p + 1)

2 个答案:

答案 0 :(得分:2)

你需要更多明星:越少越好,所以我简化了你的程序。

#include <stdio.h>
#include <stdlib.h>

int *f(int size)                    // returns a pointer
{
    int *p;                         // define a pointer
    p = malloc(size);               // allocate memory to it
    if(p == NULL) {                 // check the result
        exit(1);                    // emergency exit
    }
    *p = 200;                       // put a value at p[0];
    p[1] = 4;                       // put a value at p[1];
    return p;                       // return the pointer
}

int main(void)
{
    int *p0;                        // pointer as yet has no value assigned
    p0 = f(2 * sizeof *p0);         // get memory for 2 ints and initialise it
    printf("%d, %d\n", *p0, p0[1]); // show the two ints assigned
    free(p0);                       // release the memory
    return 0;                       // end of program
}

节目输出:

200, 4

除了较少的明星,您的计划有两个主要变化

  1. 该函数直接返回指针。通过参数设置它需要一个星。

  2. 请求的内存量是针对数据类型的两个元素,而不是&#34;硬编码&#34;。

  3. 您也可以认为有多种方法可以根据指针访问数组。

答案 1 :(得分:2)

是的,E行是个问题。实际上,你在D行已经遇到了麻烦,因为你读了p0的(未定义)值。这在C中是禁止的;它是可怕的未定义行为的一部分,这意味着所有赌注都已关闭,并且法律允许编译器输出它想要的任何内容:崩溃的二进制文件,或打印“Hello world!”,您的名字它

您正确地看到p0应指向int *缓冲区,然后才能在该缓冲区中写入。但是,不需要这种额外的间接级别。 p0可以是int *

#include <stdlib.h>
#include <stdio.h>

void f(int** ptr_p)     //C
{
    *ptr_p      = malloc(sizeof(int) * 2);  //E
    (*ptr_p)[0] = 200;        //F
    (*ptr_p)[1] = 4;          //G
}

int main(void)
{
    int* p0;             //A
    f(&p0);              //B
    printf("%d, %d\n", p0[0], p0[1]);
    free(p0);            //H
    return 0;
}

最后一件事:malloc可能会失败并返回NULL;一个强大的程序会检查它。