1

我有一种情况,我在内存中有一个很大的字符串,我想用函数来提供它的切片(例如,给我一个从 30 开始的 14 个字符的运行)。为了完成这项工作,我必须让消费者对他们的缓冲区使用双指针。

void foo(char** bar)
{
    char* tmp = "nope";
    *bar = &tmp[1];
}

int main (int argc, char const *argv[])
{
    char* baz = "yep";
    foo(&baz);
    printf("%s", baz);
    return 0;
}

但是,如果我查看各种库函数,如 pread 或 strcpy,它们只接受一个指针级别的字符串缓冲区。

他们是怎么做到的?似乎他们也应该需要一个双指针来以相同的方式“在另一边”更改值。

4

3 回答 3

6

大多数此类函数不会更改指针,它们会更改内存。的原型strcpy()是:

char * strcpy(char *dest, const char *source);

这意味着 指向的内存将被从到(包括)第一个 0 字符的dest内容覆盖。source

调用者将使用将要修改的缓冲区的地址来调用它。

对于您的情况,听起来您在进行零拷贝字符串切片之后,那么使用指向指针的指针更有意义。请注意,终止将成为一个问题,您不能在不需要复制的情况下对 C 字符串进行切片,否则原始字符串也会被切片。

您当然可以定义一个复制字符串切片函数:

char * slice_string(char *dest, size_t dest_max,
                    const char *source, int start_index, int end_index);

这会将字符从 复制sourcedest,就像 一样strcpy(),但只复制一个子字符串。例如,我对索引进行了签名,以便您可以支持负索引(例如 Python)。

请注意,该函数未调用strslice(),因为该函数名称是保留的。

于 2013-05-13T14:16:38.820 回答
3

两者都不改变指针指向的地方pread()strcpy()他们更改缓冲区包含的内容。因此,它们不需要双指针表示法。

你可能会做得最好:

const char *foo(void);

这避免了双指针,并允许您编写:

char *baz = foo();

在您的示例主程序中。

表示没有空终止的字符串切片需要注意(起始位置和长度)。也许您将使用带有指针和长度的结构,在这种情况下,您可以将指向此类结构的指针传递给您的函数,或者返回该结构的副本。

于 2013-05-13T14:18:25.000 回答
2

您需要区分指针和指针。考虑一个采用单级指针的函数,如下所示:

char *p = ...;
f(p);

f收到p. 这个拷贝指向同一个内存p,所以f可以改变内存中的值p指向,但不能改变指向哪块内存。p在合同中,一个接受双指针的函数是这样调用的:

char *p;
g(&p);

g将能够做所有f可以做的事情,使用*the_parameter(给出 的值p)。但除此之外,它可以改变p,所以它可以p指向一些不同的内存。这对于大多数功能来说不是必需的,但有时很有用。

于 2013-05-13T14:20:15.443 回答