1

我试图更多地理解 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 指针传递给函数的工作方法。我不明白的是Method 1

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

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

4

2 回答 2

6

int f(char* p)当已经指向您需要的内存位置时,是 C 中将指针传递p给函数的常用方法(通常是因为在方法 2 或方法 3 中已经在那里分配了一个字符数组)。fp

int f(char** p)当您希望能够修改此函数的调用者的指针时,这是 C 中将指针传递p给函数的常用方法。您的方法 1 就是一个例子;您想分配新内存并用于告诉调用者该内存在哪里。ffpfp

int f(char*& p)是 C++,而不是 C。由于它为您编译,我们知道您使用的是 C++ 编译器。

于 2014-07-22T15:00:29.047 回答
0

考虑当您采用类型参数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 *x通过使用指向 int ( ) 的指针并通过 (*x)++ 对其进行修改,可以实现相同的行为。这样做的唯一区别是调用者必须调用 f(&i),并且调用者可以将无效指针传递给 f。因此,引用通常更安全,应尽可能首选。

采用类型的参数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-(pointer-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**(pointer-to-pointer-to-char),并将 f 修改为 use **p = 'p'; *p = NULL,调用者必须调用 f(&s),具有相同的含义。

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

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

char**当你的char*&函数需要返回一个指向它分配的内存块的指针时,你通常会使用它。您char**会经常看到,因为这种做法在 C++ 中不如在不存在引用的 C 中常见。

至于是使用引用还是指针,这是一个备受争议的话题,如果您在 google 上搜索“c++ 指针与引用参数”,您会注意到。

于 2014-07-22T15:02:13.653 回答