C++ char 数组似乎没有传递完整数组

C++ char array seems to not pass full array

我想先说明一下,我是一名初级但经验相对丰富的开发人员,但 非常 很少有 C++ 经验。

我有这个测试方法,它应该通过一个字符数组来找到“O”。

TEST(MyTest, ReturnIndexOfO)
{
    Widget unitUnderTest;
    char x = 'X';
    char o = 'O';
    char *row[4] = {&o, &x, &x, &x};
    char *row2[4] = {&x, &o, &x, &x};

    EXPECT_EQ(unitUnderTest.findEmptySpace(*row, 4), 0);
    EXPECT_EQ(unitUnderTest.findEmptySpace(*row2,4 ), 1);
}

这已经正确调用了我的 findEmptySpace 方法,即:

#define WHITE_SPACE 'O'
int Widget::findEmptySpace(char row[], int size)
{
    cout << "The row under test is:\n";
    for(int i = 0; i < size; i++) {
        cout << row[i];
    }
    cout << "\n";
    for(int i = 0; i < size; i++) {
        if(row[i] == WHITE_SPACE) {
            return i;
        }
    }
    return -1;
}

但不幸的是,我的输出似乎表明我的 findEmptySpace 方法并未读取所有字符:

The row under test is:

OX

The row under test is:

X

所以即使使用截断的数据,我的第一个测试用例通过了,但第二个测试用例失败了。知道为什么我看不到正确的数据吗?

这个表达式

Test.findEmptySpace(*row, 4)

等同于表达式

Test.findEmptySpace(row[0], 4)

并且元素 row[0] 是一个指针,其值为 &o,指向 char

类型的标量对象 o
char o = 'O';.

因此带有此类参数的函数调用(函数内的内部循环)没有意义

看来你的意思是下面的

EXPECT_EQ(unitUnderTest.findEmptySpace(row, 4), 0);

#define WHITE_SPACE 'O'
int Widget::findEmptySpace(char * row[], int size)
{
    cout << "The row under test is:\n";
    for(int i = 0; i < size; i++) {
        cout << *row[i];
    }
    cout << "\n";
    for(int i = 0; i < size; i++) {
        if( *row[i] == WHITE_SPACE) {
            return i;
        }
    }
    return -1;
}
   char *row[4] = {&o, &x, &x, &x};

这不是“字符数组”。这是一个包含四个字符指针的数组。

unitUnderTest.findEmptySpace(*row, 4)

这会将这些指针中的第一个传递给第一个参数中的 findEmptySpace()。第一个指针是指向 o.

的指针

findEmptySpace()的第二个参数是4。这就是上述语句在C++中的作用。

函数 findEmptySpace() 执行以下操作:

    for(int i = 0; i < size; i++) {
        cout << row[i];
    }

因此它最终会打印传递给它的指针的前四个字符。

问题是传入的指针只指向一个字符:

&o

这是第一个指针。这个函数最终试图从一个只指向一个字符的指针读取前四个字符。

这会导致未定义的行为。

当你打电话时

unitUnderTest.findEmptySpace(*row, 4)

表达式 rowdecay 指向指向 row 的第一个元素的指针,即指向 &row[0]。因此,表达式*row等价于row[0],它是一个指向变量o的指针,即指向单个字符的指针。

在函数 Widget::findEmptySpace 中,在下面的循环中,您将这个指向单个字符的指针用作指向 4 个字符的指针:

for(int i = 0; i < size; i++) {
    cout << row[i];
}

由于函数参数 row(与具有该名称的原始数组相反)是指向单个字符的指针,因此 row 的唯一有效索引将是 row[0] .但是,您正在使用 row[0]row[3] 的索引,因此您正在越界访问对象,导致 undefined behavior.

函数签名

int Widget::findEmptySpace(char row[], int size)

可能不是您想要的。如果要将指向整个数组 row 的指针从函数 TEST 传递给函数 findEmptySpace,则应将指向数组第一个元素的指针及其第一个元素的指针传递给函数 findEmptySpace长度。您已经正确地完成了后者,但是您没有正确地完成前者。由于数组的每个元素都是 char * 类型,因此指向数组第一个元素的指针将是 char ** 类型,即指向指针的指针。因此,您应该将函数签名更改为以下内容:

int Widget::findEmptySpace( char **row, int size )

或者,如果您愿意,可以使用这个等价物,以明确更高级别的指针指向数组:

int Widget::findEmptySpace( char *row[], int size )

当然,您将不得不重写您的函数 findEmptySpace 以适应不同的参数类型,以便它取消引用指针:

int Widget::findEmptySpace( char *row[], int size )
{
    cout << "The row under test is:\n";

    for( int i = 0; i < size; i++ ) {
        cout << *row[i];
    }

    cout << "\n";

    for( int i = 0; i < size; i++ ) {
        if( *row[i] == WHITE_SPACE ) {
            return i;
        }
    }
    return -1;
}

现在,在函数 TEST 中,由于更改了函数参数,您必须更改调用函数 findEmptySpace 的方式。你应该改变行

EXPECT_EQ(unitUnderTest.findEmptySpace(*row, 4), 0);
EXPECT_EQ(unitUnderTest.findEmptySpace(*row2,4 ), 1);

至:

EXPECT_EQ(unitUnderTest.findEmptySpace( row, 4), 0);
EXPECT_EQ(unitUnderTest.findEmptySpace( row2, 4 ), 1);

现在您不再传递第一个数组元素的值,而是传递指向第一个数组元素的指针,以便函数 findEmptySpace 可以正确访问整个数组。