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

C 如何传递指针并在堆上分配空间,c,pointers,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]); }

我试图传递一个指向函数的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;
}
#包括
#包括
无效bla(字符*t)
{
t=(char*)malloc(5);
如果(t!=0){
t[0]='h';
printf(“%c\n”,t[0]);
}
}
int main(int argc,字符**argv)
{
charb[10];
bla(b);
printf(“%c\n”,b[0]);
返回1;
}
我不太确定它是否与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;
}
#包括
#包括
无效blub(字符**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,字符**argv)
{
char*a;
blub&a;
printf(“%d\n”,a);
printf(“%d\n”,a[0]);
printf(“%d\n”,a[1]);
返回1;
}
结果如下:

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

0您需要使用指针对指针

//............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的指针,并且需要更改它,因此使用“指向char的指针”:


编辑
根据您的编辑-是的,您已经完全理解了这一点,只是有一个小问题-
operator*
operator[]
的优先级。如果您将
*t[X]
替换为
(*t)[X]
,一切都会好起来:)

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

如果您想让函数修改该数组的内容,只需在传递过程中传递一个简单的指针(但不需要分配!):


函数完成后,
main
中的
b
的值也会更改。

如果使用指向指针的指针

void blah(char **t)
您可以使用malloc作为

*t = malloc(size);
你会这样称呼布拉:

char *b;
bla(&b);

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

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

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

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

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

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

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


最后一点是,这是一个纯C应用程序。在C++中,您将使用NeX/DELT分配/释放内存、STD::String,而不是CHAR*字符串,而STD::CUT

第二个示例中奇怪行为的原因是操作符的优先级。 [](括号,数组下标)的优先级高于*(取消引用)

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

因为t是指向char的指针:

*(t[1])
的意思是“取t的地址,前进(sizeof(char*))字节,取消对地址的引用,然后再次取消引用”

(*t)[1]
表示“获取t的地址,取消引用,向前移动(sizeof(char))字节,然后再次取消引用”


实际上,在第一种情况下,behavious是未定义的,因为它试图在t之后加倍解除对位置的限制。在您的示例中,将始终打印第一个值,因为t[0]表示仅取消引用,因此这两种情况将是相同的。

这段代码没有什么意义……别忘了在某个地方释放内存@PullyDuck-请看我的编辑:)你的方向正确。这只是一个真正问题的模型,我需要使用malloc。
char *b;
bla(&b);
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)
}