C 为什么';t strep()是否使用指向堆栈的指针?

C 为什么';t strep()是否使用指向堆栈的指针?,c,string,heap-memory,stack-memory,strsep,C,String,Heap Memory,Stack Memory,Strsep,使用函数strep查找字符串的第一个单词时,似乎存在指针兼容性问题。到目前为止,我一直认为char*s和char[]是完全可以互换的。但事实似乎并非如此。我的程序使用堆栈上的数组失败,并显示以下消息: foo.c: In function ‘main’: foo.c:9:21: warning: passing argument 1 of ‘strsep’ from incompatible pointer type [-Wincompatible-pointer-types] char *

使用函数
strep
查找字符串的第一个单词时,似乎存在指针兼容性问题。到目前为止,我一直认为
char*s
char[]
是完全可以互换的。但事实似乎并非如此。我的程序使用堆栈上的数组失败,并显示以下消息:

foo.c: In function ‘main’:
foo.c:9:21: warning: passing argument 1 of ‘strsep’ from incompatible pointer type [-Wincompatible-pointer-types]
  char *sub = strsep(&s2, " ");
                     ^
In file included from foo.c:2:0:
/usr/include/string.h:552:14: note: expected ‘char ** restrict’ but argument is of type ‘char (*)[200]’
 extern char *strsep (char **__restrict __stringp,
我不明白这个问题。使用malloc的程序运行正常

这项工作:

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

int main(void)
{
    char s1[] = "Hello world\0";
    char *s2 = malloc(strlen(s1)+1);
    strcpy(s2, s1);
    char *sub = strsep(&s2, " ");

    printf("%s\n", sub);

    return 0;
}
#包括
#包括
#包括
内部主(空)
{
char s1[]=“你好世界\0”;
char*s2=malloc(strlen(s1)+1);
strcpy(s2,s1);
char*sub=strep(&s2,“”);
printf(“%s\n”,sub);
返回0;
}
这并不是:

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

int main(void)
{
    char s1[] = "Hello world\0";
    char s2[200];
    strcpy(s2, s1);
    char *sub = strsep(&s2, " ");

    printf("%s\n", sub);

    return 0;
}
#包括
#包括
内部主(空)
{
char s1[]=“你好世界\0”;
字符s2[200];
strcpy(s2,s1);
char*sub=strep(&s2,“”);
printf(“%s\n”,sub);
返回0;
}
有什么问题吗?(很抱歉出现strcpy)。为什么指针指向堆栈还是堆对函数很重要?我理解为什么不能访问二进制/文本段中的字符串,但是堆栈有什么问题

 note: expected ‘char ** restrict’ but argument is of type ‘char (*)[200]’
您的警告会准确地告诉您问题所在。你有两种不同的类型

char *s2;        /* declares a character pointer */

当您使用指针的地址时,结果是指向指针的指针。当您获取数组的地址时,结果是指向数组的指针。将指针解引用到指针时,结果是指针。取消引用指向数组的指针时,结果是一个数组


strep
的设计目的不是将指向数组的指针作为参数(这将阻止它根据需要重新分配)

@DavidRankin正确解释了它为什么不工作。但您仍然可以编写代码,以便它可以在堆栈上使用变量

要使用数组代替malloc(),可以创建另一个指向该数组的指针,并将其用作strep()的参数,如version1()函数所示

我知道这可能只是一个示例,但是您提供的malloc()和strep()示例可能会导致内存错误,因为strep()将更新指针(它修改它指向的地址)。因此,您必须保存malloc()返回的原始地址,以便正确地释放该内存。请参见version2()示例

#包括
#包括
#包括
作废版本1(作废)
{
char s1[]=“你好,世界”;
字符s2[200];
char*s3=s2;
char*sub;
strcpy(s3,s1);//或s2代替s3
while((sub=strep(&s3,“”))
{
printf(“%s\n”,sub);
}
}
作废版本2(作废)
{
char s1[]=“你好,世界”;
char*mymem=malloc(strlen(s1)+1);
char*s2=mymem;
char*sub;
strcpy(s2,s1);
while((sub=strep(&s2,“”))
{
printf(“%s\n”,sub);
}
免费(mymem);
}
int main(int argc,char*argv[])
{
printf(“版本1\n”);
版本1();
printf(“\n版本2\n”);
版本2();
返回0;
}

我很确定第二个示例中的
&s2
返回一个
字符**
?打开编译器警告。您应该只使用
s2
,或者
&s2[0]
,如果您愿意的话。数组已被转换为指针。@YoYoYonnY这些将导致
char*
strsep
的第一个参数是
char**
。您需要
strsep
char**
,以便它可以修改它。在第二个示例中,
&s2
的类型为
char(*)[200]
,这是非常不同且不兼容的。它需要修改指针,在这种情况下显然无法修改。@Yoony不正确<第二个示例中的code>&s2具有类型
char(*)[200]
,这与
char**
不兼容。但为什么它们在其他地方完全可以互换?您可以使用指针对数据进行索引,就像您对带有
pt[i]
@TheoFreeman的数组所做的那样。它们不是完全可互换的,但它们是密切相关的。了解这一点可以解释数组如何在访问时转换为指针。虽然这允许具有自动存储持续时间的阵列和动态分配的阵列在某些情况下可以互换使用,但它不会更改基础类型。问题是当函数需要指向指针的指针时,例如,
char*stresp(char**stringp,const char*delim)
ssize\u t getline(字符**lineptr,大小*n,文件*流)
char s2[200];   /* declares an array of char[200] */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void version1(void)
{
    char s1[] = "Hello world";
    char s2[200];
    char* s3 = s2;
    char *sub;

    strcpy(s3, s1); // or s2 in place of s3

    while ((sub = strsep(&s3, " ")))
    {
        printf("%s\n", sub);
    }
}

void version2(void)
{
    char s1[] = "Hello world";
    char *mymem = malloc(strlen(s1)+1);
    char *s2 = mymem;
    char *sub;

    strcpy(s2, s1);

    while ((sub = strsep(&s2, " ")))
    {
        printf("%s\n", sub);
    }

    free(mymem);
}

int main(int argc, char* argv[])
{
    printf("Version1\n");
    version1();

    printf("\nVersion2\n");
    version2();

    return 0;
}