如何传递指针并在堆上分配空间
我试图向一个函数提供一个char指针,然后用它填充它,以便调用函数可以使用它。 因为它总是在调用函数中给我奇怪的东西,我写了一个关于我所做的简单表示:
#include #include 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传递参数副本是否有事可做。 我需要将指针传递给指针,还是有更好的解决方案?
编辑:
对不起的家伙,但我没有得到它。 你能看一下这个例子:
#include #include 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中它是一个空指针?! 我完全糊涂了:/
你需要使用指针指针。
//............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]
(*t)[X]
,每个都可以正常:)
如果使用指针指针
void blah(char **t)
你可以使用malloc as来分配一个内存块(在头部)
*t = malloc(size);
你会这样称呼blah:
char *b; bla(&b);
它将被分配并用blah填充,结果可以打印在main中。
你正在传递一个指向函数的指针。 通过它,你可以永久地改变(在函数返回之后)只指向它指向的对象,但你不能改变指针本身,因为它是实际传递给函数的副本。 函数内的所有更改都在指针的副本上进行。 当函数返回时,其原始值保持不变。
(1)如果要在某个函数中更改某个变量,则需要将其指针传递给它。 如果该变量是指针类型,则传递一个指向它的指针 – 一个指向指针的指针! 在您的情况下,该变量将是char **类型。
(2)如果要在函数中的堆上分配内存,则不需要使用堆栈 – 将指针b声明为char *。
(3)在堆上分配内存后,不要忘记解除分配,否则最终会导致内存泄漏。
(4)如果应用程序终止且没有错误,则从应用程序返回0。 保留错误代码的其他返回值 – 如果您的应用中可能出现不同的错误,请返回不同的代码。
最后一点是这是一个纯C应用程序。 在C ++中,您将使用new / delete来分配/释放内存,std :: string而不是char *用于字符串,而std :: cout <<而不是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) }
当你写char b[10];
如果你有一个静态分配的数组,你不需要为它分配更多的空间,它最多可以容纳10个char
值。
如果你想让你的函数修改那个数组的内容,你只需要传递一个简单的指针(但没有分配!):
void bla(char *t) { if (t != 0) { t[0] = 'h'; printf("%c\n", t[0]); } }
在该function之后, main
的b
值也会发生变化。
如果你想使用var引用返回结果然后是,你必须将指针传递给指针,(或者只是以通常的方式返回结果,char * bla())。 不要忘记null终止符!
第二个例子中出现奇怪行为的原因是运营商的优先级。 [](括号,数组下标)的优先级高于*(取消引用)
因此, *t[1]
与*(t[1]).
你需要(*t)[1]
因为t是指向char的指针:
*(t[1])
表示“将t的地址,go(sizeof(char *))字节提前,取消引用地址,然后再取消引用”
(*t)[1]
表示“取t的地址,取消引用它,go(sizeof(char))字节前进并再次取消引用”
实际上在第一种情况下,行为是未定义的,因为它试图在t之后双重取消对位置的影响。 在您的示例中,将始终打印第一个值,因为t [0]仅表示取消引用,因此两个案例将是相同的。