如何传递指针并在堆上分配空间

时间:2011-10-28 08:49:14

标签: c pointers

我正在尝试向函数提供一个char指针,然后用它填充它,以便调用函数可以使用它。因为它总是在调用函数中给我奇怪的东西,我写了一个关于我所做的简单表示:

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

void bla(char *t)
{
    t = (char*) malloc(5);
    if (t != 0) {
        t[0] = 'h';
        printf("%c\n", t[0]);
    }
}

int main(int argc, char **argv)
{
    char b[10];

    bla(b);
    printf("%c\n", b[0]);
    return 1;
}

我不太确定C是否有事要做,C传递了参数的副本。我是否需要将指针传递给指针,或者是否有更好的解决方案?

编辑:

对不起伙计但我没有得到它。你能看一下这个例子:

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

void blub(char **t)
{
    printf("%d\n", *t);
    *t = (char*) malloc(sizeof(char) * 5);
    *t[0] = 'a';
    *t[1] = 'b';
    printf("%d\n", *t);
    printf("%d\n", *t[0]);
    printf("%d\n", *t[1]);
}

int main(int argc, char **argv)
{
    char *a;
    blub(&a);
    printf("%d\n", a);
    printf("%d\n", a[0]);
    printf("%d\n", a[1]);

    return 1;
}

输出如下:

./main
6154128
140488712
97
98
140488712
97
0      <== THIS SHOULD BE 98 AS ABOVE!?

为什么我在函数blafu中获得98,而在main中它是一个空指针?!我完全糊涂了:/

6 个答案:

答案 0 :(得分:7)

您需要使用指针指针。

//............vv
void bla(char **t)

然后通过解除引用来使用指针:

// note the '*' in front of t
*t = (char*) malloc(5);
if (*t != 0) {
    *t[0] = 'h';
    printf("%c\n", *t[0]);
}

另外,将b声明为char*,而不是char b[10]


为什么呢?因为您正在尝试更改指针。逻辑与其他类型相同,但这里有点令人困惑 想一想:如果你需要传递一个int而你需要更改它,你需要一个指向int 的指针。同样在这里 - 你需要传递指向char 的指针,你需要你改变它,所以使用&#34; 指向指向char的指针 &#34; :)


修改 的: 根据您的编辑 - 是的,您已完全理解这一点,这只是一个小问题 - operator*operator[]的优先级。如果您将*t[X]替换为(*t)[X],那么每个人都会没问题。)

答案 1 :(得分:2)

如果使用指向指针的指针

void blah(char **t)

你可以使用malloc作为

分配一个内存块(在头部)
*t = malloc(size);

你可以这样称呼:

char *b;
bla(&b);

它将被分配并用blah填充,结果可以打印在main中。

答案 2 :(得分:1)

您正在传递指向函数的指针。通过它,你可以永久地改变(在函数返回之后)只指向它指向的对象,但你不能改变指针本身,因为它是实际传递给函数的副本。函数内的所有更改都在指针的副本上进行。当函数返回时,其原始值保持不变。

(1)如果要在某个函数中更改某个变量,则需要将其指针传递给它。如果该变量是指针类型,则传递一个指向它的指针 - 一个指向指针的指针!在您的情况下,该变量将是char **类型。

(2)如果要在函数中的堆上分配内存,则不需要使用堆栈 - 将指针b声明为char *。

(3)在堆上分配内存后,不要忘记取消分配内存,否则最终会导致内存泄漏。

(4)如果应用程序终止且没有错误,则从应用程序返回0。保留其他返回值 对于错误代码 - 如果您的应用中可能出现不同的错误,请返回不同的代码。

最后一点是这是一个纯C应用程序。在C ++中,您将使用new / delete来分配/释放内存,使用std :: string而不是char *来表示字符串,并使用std :: cout&lt;&lt;而不是printf用于将文本发送到输出流

void bla(char **pt)               // (1)
{
    *pt = (char*)malloc(5);

    if (*pt != 0) 
    {
        *pt[0] = 'h';
        printf("%c\n", *pt[0]);
    }
}

int main(int argc, char **argv)
{
    char* b = 0;                  // (2)

    bla(&b);
    printf("%c\n", b[0]);

    if(b)
    {
        free(b);                  // (3)
        b = 0;
    }

    return 0;                     // (4)
}

答案 3 :(得分:0)

当你编写char b[10];时,你有一个静态分配的数组,你不需要为它分配更多的空间,它最多可以容纳10 char个值。

如果你想让你的函数修改那个数组的内容,你只需要传递一个简单的指针(但没有分配!):

void bla(char *t)
{
    if (t != 0) {
        t[0] = 'h';
        printf("%c\n", t[0]);
    }
}

在此功能之后,bmain的值也会发生变化。

答案 4 :(得分:0)

如果你想使用var引用返回结果,那么是的,你必须将指针传递给指针,(或者只是以通常的方式返回结果,char * bla())。不要忘记null终止符!

答案 5 :(得分:0)

第二个例子中出现奇怪行为的原因是运营商的优先级。 [](括号,数组下标)的优先级高于*(取消引用)

因此,*t[1]*(t[1]).相同您需要(*t)[1]

因为t是指向char的指针:

*(t[1])表示“取t的地址,go(sizeof(char *))字节,取消引用地址,再解除引用”

(*t)[1]表示“取t的地址,取消引用它,go(sizeof(char))字节,然后再取消引用”

实际上在第一种情况下,行为是未定义的,因为它试图在t之后双重取消对位置的影响。在您的示例中,将始终打印第一个值,因为t [0]仅表示取消引用,因此两个案例将是相同的。