使用功能strsep
来查找字符串的第一个单词似乎存在指针兼容性问题。到目前为止,我一直认为char *s
和char s[]
是完全可以互换的。但是看来它们不是。我的程序在堆栈上使用数组失败,并显示以下消息:
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;
}
这不是:
#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;
}
有什么问题? (对strcpy
很抱歉)。为什么指针指向堆栈或堆对函数很重要?我知道为什么您不能访问二进制/文本段中的字符串,但是堆栈有什么问题?
答案 0 :(得分:6)
note: expected ‘char ** restrict’ but argument is of type ‘char (*)[200]’
您的警告会告诉您确切的问题所在。您有两种不同的类型。
char *s2; /* declares a character pointer */
同时
char s2[200]; /* declares an array of char[200] */
当您使用指针的地址时,结果将是 pointer-to-pointer 。当您使用数组的地址时,结果为指向数组的指针。当取消引用 pointer-to-pointer 时,结果为指针。当您取消引用指向数组的指针时,结果为一个数组。
strsep
的设计目的不是将 pointer-to-array 作为参数(这将阻止它根据需要重新分配)
答案 1 :(得分:2)
@DavidRankin 关于为什么它不起作用是正确的。但是您仍然可以编写代码,以便它可以使用堆栈上的变量。
要使用数组代替 malloc(),您可以创建另一个指向该数组的指针,并将其用作 strsep() 的参数,如 version1() 函数所示。
我知道这可能只是一个示例,但是您提供的 malloc() 和 strsep() 示例可能会导致内存错误,因为 strsep() 将更新指针(它会修改它指向的地址)。因此,您必须保存 malloc() 返回的原始地址,以便正确释放该内存。参见 version2() 示例。
#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;
}