保证有效字符串作为函数参数

时间:2013-06-09 11:59:41

标签: c++ pointers reference

我想知道在C ++中是否有一种方法可以假定传递给函数的“字符串”(以任何表示形式)是该函数的有效字符串。

我对C / C ++很新,但据我所知,在C中,默认情况下会回答这个问题,因为没有别的办法,你只知道你必须检查:

#include <stdio.h>

void foo(const char *str)
{
    if (str)
        printf("%s\n", str);
}

int main()
{
    char *name = "Jack";
    foo(name);

    return 0;
}

但是由于C ++提供了额外的东西,比如引用,我想知道是否可以以不必检查的方式编写foo()。我试过这样的话:

#include <iostream>
#include <string>

void foo(const std::string &str)
{
    std::cout << str << std::endl;
}

int main(void)
{
    std::string name = "Jack";
    foo(name);

    std::string *str = NULL;
    foo(*str);

    return 0;
}

但是你可以看到我可以欺骗foo()进入SegFault。所以,我想你只是总是必须检查,无论如何?

编辑#1:

好的,首先感谢您的所有答案和未来的答案,我们非常感谢!

总结到目前为止我学到的东西:

在C ++中没有编写函数定义的语法方法 通过实际函数调用消除误用。

这是对的吗?如果是这样,我会将原来的问题视为已回答。

所以现在我试图尽可能地将foo()写为防御性的,这样无论你对foo()如何对待狗,它都不会产生SegFault。

在C中我现在会这样写(假设是短路评估):

#include <stdio.h>

void foo(const char *str, const size_t len)
{
    if (str && (str[len - 1] == '\0'))
        printf("%s\n", str);
}

int main()
{
    char *name = "Jack";
    foo(name, 5);

    /* possible mistakes, but foo can handle them */
    foo(name, 4);
    foo(name, -1);
    foo(NULL, 5);

    return 0;
}

在C ++中,我正在尝试这个:

#include <iostream>
#include <string>

void foo(const std::string &str)
{
    if (&str)
        std::cout << str << std::endl;
}

int main(void)
{
    std::string name = "Jack";
    foo(name);

    std::string *str = NULL;
    foo(*str);

    return 0;
}

...但我不确定这是否属于任何适当的情况,或者在这种情况下是否会,可能或应该对例外做什么。

你怎么看?如果你不能通过语法来防止滥用,你必须增加预防措施吗?

2 个答案:

答案 0 :(得分:9)

std::string *str = NULL;
foo(*str);

这是调用者方面的未定义行为。不是你的问题。所以不,你(foo的作者)不必检查。

即使在C中,使用指针,您也不必检查。你只需要记录。 “参数必须指向一个有效的以空字符结尾的字符串。如果不是,则调用是未定义的行为。” - 如果用户传递NULL,也就是说,他们的问题。这是一直这样做的。如果不是,那么你会有浪费的调用链在每个级别上检查指针的有效性,如下所示:

void foo(const char * s)
{
    if (s)
        printf("%s", s);
}

void bar(const char * s)
{
    if (s)
        foo(s);
}

void baz(const char * s)
{
    if (s)
        bar(s);
}

答案 1 :(得分:2)

不,你不对。

在第二个代码中,当您取消引用指针时会发生未定义的行为,之前进入您的函数。

这不是您的功能问题。在你的函数中,使用第二个签名,你总是可以假设你有一个有效的字符串,这使它优于第一个。