C 通过引用将 char 指针传递到执行 strtok() 的函数中,但在返回后打印意外结果

C pass char pointer by reference into a function executing strtok() but after returned print unexpected results

提问人:Learning 提问时间:10/27/2022 最后编辑:Vlad from MoscowLearning 更新时间:10/27/2022 访问量:64

问:

我想在 C 中通过引用测试通过指针,下面是我的测试代码。

我希望结果是:,但是在我执行后,我发现结果是不确定的。"World!"

void parse(char **p)
{
    char str[] = "Hello World!";

    char *token = strtok(str, " "); // token points to 'H'
    *p = strtok(NULL, " "); // *p (buf) points to 'W'

}

int main() 
{
    char *buf = (char*)malloc(20 * sizeof(char));

    buf = "How are you?";

    parse(&buf);

    printf("%s\n", buf);
}

我的观点:

(1)在:中指向(的第一个字符)(假设地址是main()buf'H'"How are you?"'H''H'0x10)

(2) 将指针指向(即parse(&buf)pbuf*p = buf = 0x10)

(3) 2 次后,() 指向 (假设 的地址为strtok()*pbuf'W''W'0x20)

(4)现在,返回 ,指向main()buf0x20


(5) 我希望应该打印,但应该打印类似“乱码”的东西。printf("%s\n", buf);"World!"

我尝试过调试,但我认为我没有弄错上面的任何内容。

有人能平息我的疑虑吗?

提前致谢。

按引用传递 c-strings strtok 存储持续时间

评论

1赞 Barmar 10/27/2022
buf = "How are you?";应该是strcpy(buf, "How are you?");
2赞 Barmar 10/27/2022
返回时,局部数组以及指向它的任何指针将失效。所以你会导致未定义的行为。strparse()printf()
0赞 Learning 10/27/2022
@Barmar(根据第一条评论)是的,我也尝试过这个,但这不是导致意外结果的主要问题。
0赞 Pablo 10/27/2022
*p = strtok(NULL, " ");替换指向的位置,它不会复制内容。buf
2赞 Barmar 10/27/2022
这些代码中有很多是没有意义的。如果您要重新分配内存,为什么要费心分配内存,首先使用 ,然后再次使用 。您有内存泄漏,因为您无法分配内存。为什么解析的是本地字符串而不是传递给它的字符串?bufbuf = "How are you?"parse(&buf)free()parse()

答:

1赞 Vlad from Moscow 10/27/2022 #1

此代码片段

char *buf = (char*)malloc(20 * sizeof(char));

buf = "How are you?";

产生内存泄漏。

起初,内存是动态分配的,其地址被分配给指针 buf,然后用字符串文字的第一个字符的地址重新分配指针。因此,分配的内存的地址丢失。

此外,您不能更改字符串文本。任何更改字符串文本的尝试都会导致未定义的行为,

你至少应该写

strcpy( buf, "How are you?" );

至于函数,则其具有自动存储持续时间的本地数组

void parse(char **p)
{
    char str[] = "Hello World!";
    //...

退出函数后将不存活。因此,指针 buf 将具有无效值。

例如,该程序可以按以下方式查找

#include <stdio.h>
#include <string.h>

void parse( char *s, char **p)
{
    *p = strtok( s, " " );
    *p = strtok(NULL, " ");
}

int main() 
{
    char str[] = "Hello World!";

    char *buf;

    parse( str, &buf );

    if ( buf ) printf("%s\n", buf);
}

评论

0赞 Learning 10/27/2022
因为这是一个测试代码,只是测试 C 语言中通过引用传递的工作原理,所以我试图简化代码并忽略内存泄漏问题,实际上主要问题是局部变量的生存期。谢谢
0赞 chqrlie 10/27/2022
@Learning:实际上是您必须解决的问题:指向字符串文字,该文字是常量,不得修改。 创建一个使用字符串文本副本初始化的局部数组,该函数可以修改该数组作为调用 的副作用。理解工作原理的一个很好的练习是重写它。buf = "How are you?";bufchar buf[] = "Hello World!";bufparsestrtok()strtok()