首页 文章

指向函数中的字符串

提问于
浏览
5

似乎我坚持一些基础知识 . 有人可以解释我为什么下一个代码:

#include <stdlib.h>

void Test1(char *t)
{
    t = (char *)malloc(11);
    strcpy(t, "1234567890");
}

void Test2(char **t)
{
    *t = (char *)malloc(11);
    strcpy(*t, "1234567890");
}

void Test3(char *t)
{
    strcpy(t, "1234567890");
}

char * Test4(char *t)
{
    t = (char *)malloc(11);
    strcpy(t, "1234567890");
    return t;
}

int main()
{
    char *t1 = NULL;
    Test1(t1);
    printf("\nTest1: %s\n", t1);

    char *t2 = NULL;
    Test2(&t2);
    printf("\nTest2: %s\n", t2);

    char *t3 = (char *)malloc(11);
    Test3(t3);
    printf("\nTest3: %s\n", t3);

    char *t4 = NULL;
    t4 = Test4(t4);
    printf("\nTest4: %s\n", t4);

    return 0;
}

给出这个输出:

Test1: (null)

Test2: 1234567890

Test3: 1234567890

Test4: 1234567890

Test1功能有什么问题?为什么Test4与Test1几乎相似?更一般的问题:在函数中创建字符串并返回指针的正确方法是什么?

9 回答

  • 1
    void Test1( char*& t ) ; // This is a possible method signature.
    
  • 3

    考虑您的Test1执行以下行为:

    char * x1 = NULL;
    Test1 (x1);
    

    Test1在以下内容中完成:

    void test1 (char * t) / / t -> x1 -> null
    {
        t = (char *) malloc (11);
        // t now points a different place (the memory allocated), and the reference of x1 continues pointing to null
        strcpy (t, "1234567890"); // t value is "1234567890" but x1 continues pointing to null
        // Error, the memory that is pointed by t is never released
    }
    
    printf ("\nTest1:%s \n", t1); / / Print the value of x1 (null) and the reference of t is lost
    
  • 3

    功能参数不像您想象的那样工作 . 您通过“值”而不是“引用”传递值,这意味着一旦进入函数,对这些值的任何更改都只对该函数是本地的,因此当函数退出时,本地更改将被丢弃 .

    要解决这个问题,要么传入指向指针的指针(char ** t),要么通过引用传递指针(char&*)并更改功能代码以匹配 .

  • 2

    你已经将t1定义为 char* t1 = NULL; 并将函数调用为 Test1(t1); 传递指针变量t1(而不是其地址) .

    函数Test1期待一个char * void Test1(char *t)

    这里 t 只是 Test1 函数的本地变量 . 您在函数内部执行的任何修改都不会在函数旁边显示,因为您实际上并未修改 main 函数的变量 t1 ,而是修改局部变量 t .

  • 3

    Test1 中,将变量 t 传递给函数,该函数是指针 . Parameters passed to the functions lives in the stack, and when the function completes, the stack is lost. main()中t为NULL的原因是您将malloc的结果存储在堆栈中,并且该堆栈不再存在 .

  • 2

    将指针作为参数传递给函数时,指针将按值传递 . 因此,您可以更改指向的对象,但如果您修改了函数中的指针,则调用者将不会知道它 .

  • 4

    考虑功能:

    void Test1(char *t)
    {
        t = (char *)malloc(11);
        strcpy(t, "1234567890");
    }
    

    现在, t 是函数中的局部变量 . 它包含什么?指针值 . 最初,指针值指向 NULL ,因为您将其称为 Test1( NULL ); .

    但是第一行 t = (char *)malloc(11) 将局部变量 t 重新分配给一个新的malloc内存 .

    当函数返回 main() 变量 t1 仍然指向 NULL 因为,记得我之前说过, Test1 函数获取指针值的副本 . t1 变量从未被 Test1 修改过 .

    但是,如果您将函数编码为:

    void Test1(char **t) {
        *t = (char *)malloc(11);
        strcpy( *t, "1234567890" );
    }
    
    int main( void ) {
        ...
        Test1( &t1 );
        ...
    }
    

    ......会有所不同 .

  • 0

    因为你写的是:

    void Test1(char *t)
    

    将此更改为:

    void Test1(char* &t)
    

    将在C Only中工作 . 演示在这里:http://www.ideone.com/OYNQo

  • 7

    在Test1中,该行

    t = (char *)malloc(11);
    

    分配给变量t,它在函数Test1中是局部的 . main()中的变量t1没有改变,因此NULL指针传递给printf . Test4有效,因为你改变了main()中的t4 .

    在函数中创建字符串的“正确”方法是Test4(但您不需要提供t作为参数)或Test2(如果您更喜欢或需要out参数) . 在这两种情况下,调用者必须在之后释放字符串 . Test3也可以工作,但是调用者必须确保缓冲区足够大 - 为了防止未定义的行为和内存泄漏,缓冲区大小应该作为参数传递给Test3 . 使用Test3的优点是可以在堆栈中分配缓冲区,从而消除内存泄漏的风险 .

相关问题