将char指针/数组传递给函数

时间:2014-07-22 14:33:11

标签: c++ c pointers char char-pointer

我试图更多地了解C中的char指针,但有一件事让我感到兴奋。

假设我想将char指针传递给函数并更改指针所代表的值。一个例子如下:

int Foo (char *(&Msg1), char* Msg2, char* Msg3){
    char *MsgT = (char*)malloc(sizeof(char)*60);
    strcpy(MsgT,"Foo - TEST");
    Msg1 = MsgT; // Copy address to pointer
    strcpy(Msg2,MsgT); // Copy string to char array
    strcpy(Msg3,MsgT); // Copy string to char pointer
    return 0;
}

int main() {
    char* Msg1; // Initial char pointer
    char Msg2[10]; // Initial char array
    char* Msg3 = (char*)malloc(sizeof(char) * 10); // Preallocate pointer memory
    Foo(Msg1, Msg2, Msg3);
    printf("Msg1: %s\n",Msg1); // Method 1
    printf("Msg2: %s\n",Msg2); // Method 2
    printf("Msg3: %s\n",Msg3); // Method 3
    free(Msg1);    
    free(Msg3);
    return 0;
}

在上面的例子中,我列出了我知道的将char指针传递给函数的所有工作方法。我不明白的是方法1

传递给函数 char *(&Msg1) 的第一个参数 Foo 的含义是什么?

此外,书籍和教程似乎广泛引入了方法2 method3 ,其中一些甚至将这些方法称为最正确的方法传递数组/指针。我不知道方法1 对我来说非常好看,特别是当我编写API时,用户可以轻松地将空指针传递给函数而无需预先分配内存。如果用户忘记释放内存块,则唯一的缺点可能是潜在的内存泄漏(与方法3 相同)。我们是否应该更喜欢使用方法2或3 而不是方法3

2 个答案:

答案 0 :(得分:7)

int f(char* p)已经指向您需要的内存位置时,

p是C中通常将指针f传递给函数p的常用方法(通常是因为那里)是已在方法2或方法3中分配的字符数组。

当您希望int f(char** p)能够修改指针p时,

f是C中通常将指针f传递给函数p的方法}对于此函数的调用者。你的方法1就是一个例子;您希望f分配新内存并使用p告诉调用者该内存的位置。

int f(char*& p)是C ++,而不是C.因为这为你编译,我们知道你正在使用C ++编译器。

答案 1 :(得分:1)

考虑当你使用int&类型的参数(引用int)时会发生什么:

void f(int &x) {
    x++;
}

void g(int x) {
    x++;
}

int main() {
    int i = 5;
    f(i);
    assert(i == 6);
    g(i);
    assert(i == 6);
}

通过指向int(int *x)并通过(* x)++修改它,可以实现相同的行为。这样做的唯一区别是调用者必须调用f(& i),并且调用者可以将无效指针传递给f。因此,参考文献通常更安全,应尽可能优先使用。

使用char*类型的参数(指向char的指针)意味着调用者和函数都看到相同的内存块"通过"那个指针。如果函数修改了char*指向的内存,它将持续存在于调用者:

void f(char* p) {
    (*p) = 'p';
    p = NULL; //no efect outside the function
}

int main() {
    char *s = new char[4];
    strcpy(s, "die");
    char *address = s; //the address which s points to
    f(s);
    assert(strcmp(s, "pie") == 0);
    assert(s == address); //the 'value' of the variable s, meaning the actual addres that is pointed to by it, has not changed
}

使用类型为char*&的参数(reference-to-(指向char的指针))与采用int&:大致相同: 如果函数修改了指针指向的内存,则调用者将照常查看它。但是,如果函数修改指针的(其地址),调用者也会看到它。

void f(char* &p) {
    (*p) = 'p';
    p = NULL;
}

int main() {
    char *s = new char[4];
    strcpy(s, "die");
    char *address = s; //the address which s points to
    f(s);
    assert(strcmp(address, "pie") == 0); //the block that s initially pointed to was modified
    assert(s == NULL); //the 'value' of the variable s, meaning the actual addres that is pointed to by it, was changed to NULL by the function
}

同样,您可以使用char**(指向指针指向char),并修改f以使用**p = 'p'; *p = NULL,并且调用者必须调用f(& s) ,具有相同的含义。

请注意,您不能通过引用传递数组,即如果s被定义为char s[4],则第二个示例中的调用f(s)将生成编译器错误。

另请注意,这仅适用于C ++,因为C没有引用,只有指针。

当函数需要返回指向它所分配的内存块的指针时,通常会使用char**char*&。您更频繁地看到char**,因为这种做法在C ++中比在不存在引用的C中更少见。

至于是否使用引用或指针,这是一个备受争议的主题,因为你会注意到你在谷歌搜索" c ++指针与参考参数"。