0

据我所知,标准 strcmp 函数如下所示:

int strcmp(const char* string1, const char* string2)
{
    while(*pString1++ == *pString2++)
    {
        if(*pString1 == 0) return 0;
    }
    return *pString1 - pString2;
}

我的问题是,这不会增加传递给 strcmp 的指针吗?在下面的示例中,它似乎会丢弃指针并导致发生无效的事情。

const char* string1 = "blah";
const char* string2 = "blah";
const char* string3 = "blah";
if(strcmp(string1, string2) {doSomething();} 
// Won't this make string1 = "" because it incremented the pointer to the end?
else if (strcmp(string1, string3) {doSomethingElse();}

抱歉,我只是感到困惑,因为似乎如果我将一个指针传递给 strcmp,我不应该期望该指针突然包含一个空字符串。似乎 strcmp 应该采用 const char* const。我完全误解了什么吗?

4

7 回答 7

8

您的误解是这样的:参数是通过值(副本)传递的,但您似乎认为它们是通过引用传递的。

您可以通过将参数声明strcmp为引用来获得预期的行为,如下所示:

int strcmp(const char*& string1, const char*& string2)
于 2012-05-30T15:29:27.563 回答
4

不,指针string1string2是函数的本地(按值传递)。调用者看不到对它们所做的任何更改。

于 2012-05-30T15:27:58.783 回答
1

指针本身是按值传递的,因此尽管它是指向某物的指针,但更改它只会更改本地声明。

为了能够从函数的内部范围修改指针本身,您需要有一个指向 char 指针的指针。

于 2012-05-30T15:28:11.707 回答
1

指针是按值传递的,strcmp 使用的是您发送的指针的副本,因此不会触及原始指针。

于 2012-05-30T15:28:13.737 回答
0

试试这个,你会发现它们是完全不同的指针。导致您误解的原因是它们指向同一个区域

#include <iostream>

using namespace std;

int strcmp2(char const *s1, char const *s2)
{
    cout << "In strcmp" << endl;
    cout << &s1 << " " << &s2 << endl;
    cout << endl;
}

int main()
{
    char a[100];
    char b[100];

    cout << "In main function" << endl;
    cout << &a << " " << &b << endl;
    cout << endl;

    strcmp2(a, b);
}
于 2012-05-30T15:43:36.973 回答
0

首先,经典的混淆实现strcmp更加简单:

int
strcmp(char const* s1, char const* s2)
{
    while ( *s1 ++ == *s2 ++ )
        ;
    return *s1 - *s2;
}

(我希望没有人会在实践中真正编写这样的代码。)

至于您的实际问题:C++(和 C,因为这实际上是一个 C 问题)按值传递参数,因此任何strcmp获取的指针都是副本;它不可能修改调用代码中的任何指针。所有制作参数char const* const都意味着 strcmp无法修改其指针的本地副本。

于 2012-05-30T15:32:59.050 回答
0

C++ 将参数“按值”传递给函数。考虑这段代码:

void f(int i) { i = 7; }
...
    int j = 0;
    f(j);
    assert(j == 0);

变量与变量j无关i。确实,i函数的本地f。它使用 的副本进行初始化j。更改i永远不会传达给j.

现在考虑这段代码:

void f(char *i) { i = i + 1; }
...
    char *j = "Hello";
    f(j);
    assert(*j == 'H');

同样,i用 的副本初始化j。更改i永远不会传回给j.


注意:因此可以强制“通过引用”初始化参数:

void f(int& i) { i = 7; }
...
   int j = 3;
   f(j);
   assert(j==7);

在这种情况下,不是用 的副本初始化,j而是i绑定一个j. 但这仅适用于您&在声明中的情况。

于 2012-05-30T15:33:31.533 回答