简体   繁体   English

为什么 strsep() 不能使用指向堆栈的指针?

[英]Why doesn't strsep() work with pointers to the stack?

It appears that there is a pointer compatibility problem using the function strsep to find the first word of a string.使用函数strsep查找字符串的第一个单词似乎存在指针兼容性问题。 So far I always thought that char *s and char s[] are completely interchangeable.到目前为止,我一直认为char *schar s[]是完全可以互换的。 But it appears they are not.但看起来他们不是。 My program using an array on the stack fails with the message:我在堆栈上使用数组的程序失败并显示以下消息:

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,

I do not understand the problem.我不明白这个问题。 The program using malloc works.使用malloc的程序有效。

This works:这有效:

#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;
}

This doesn't:这不会:

#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;
}

What's the issue?有什么问题? (Sorry for strcpy ). (对不起strcpy )。 Why does it matter to functions wether a pointer points towards stack or heap?为什么指针指向堆栈或堆对函数很重要? I understand why you can't access strings in the binary/text segment, but what's the issue with the stack?我明白为什么你不能访问二进制/文本段中的字符串,但是堆栈有什么问题?

 note: expected ‘char ** restrict’ but argument is of type ‘char (*)[200]’

Your warning tells you exactly what the problem is.您的警告会准确地告诉您问题是什么。 You have two different types.你有两种不同的类型。

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

while尽管

char s2[200];   /* declares an array of char[200] */

When you take the address of a pointer, the results is a pointer-to-pointer .当您获取指针的地址时,结果是一个指向指针的指针 When you take the address of an array, the results is a pointer-to-array .当您获取数组的地址时,结果是指向数组指针 When you dereference a pointer-to-pointer , the result is a pointer .当您取消引用一个指向指针的指针时,结果是一个指针 When you dereference a pointer-to-array , the result is an array .当您取消引用指向数组指针时,结果是一个数组

strsep wasn't designed to take a pointer-to-array as an argument (which would prevent it from reallocating as needed) strsep并非旨在将指向数组指针作为参数(这会阻止它根据需要重新分配)

@DavidRankin is correct as to why it doesn't work. @DavidRankin 关于为什么它不起作用是正确的。 But you can still write code so it can use a variable on the stack.但是您仍然可以编写代码,以便它可以使用堆栈上的变量。

To use an array in place of malloc(), you can create another pointer to the array and use that as your parameter to strsep() as shown in version1() function.要使用数组代替 malloc(),您可以创建另一个指向该数组的指针,并将其用作 strsep() 的参数,如 version1() 函数中所示。

I know this may just be an example, but your provided example with malloc() and strsep() can lead to memory errors since strsep() will update the pointer (it modifies the address it points to).我知道这可能只是一个示例,但是您提供的 malloc() 和 strsep() 示例可能会导致内存错误,因为 strsep() 将更新指针(它会修改它指向的地址)。 So you must save off the original address returned by malloc() in order to properly free that memory.因此,您必须保存 malloc() 返回的原始地址,以便正确释放该内存。 See version2() example.请参阅 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM