我正在使用 GTest 库为
memcmp
函数的各种实现编写测试。为了将我的实现与 memcmp
实现进行比较,我还检查了 memcmp
结果,但在最近更改代码后,它开始给出意想不到的结果。
这是我的测试代码。我已经注释掉了所有不影响问题的部分。我只提供未注释的部分。
#include <gtest/gtest.h>
using namespace std::string_literals;
struct MemcmpTestCase {
std::string s1;
std::string s2;
int n;
int result;
};
std::vector<MemcmpTestCase> testCases {
{ "", "", 0, 0 },
{ "", "1", 0, 0 },
{ "", "1", 20, 0-'1' },
{ "1", "", 0, 0 },
{ "1", "", 20, '1' },
{ "123456789", "", 5, '1' },
{ "123456789", "1234", 5, '5' },
{ "123456789", "12345", 5, 0 },
{ "", "123456789", 5, -'1' },
{ "123", "123", 0, 0 },
{ "123", "123", 1, 0 },
{ "123", "123", 2, 0 },
{ "123", "123", 3, 0 },
{ "123", "123", 4, 0 },
{ "123", "qwe", 0, 0 },
{ "123", "qwe", 1, '1'-'q' },
{ "123", "qwe", 2, '1'-'q' },
{ "123", "qwe", 3, '1'-'q' },
{ "123", "qwe", 4, '1'-'q' },
{ "123_A", "123_B", 0, 0 },
{ "123_A", "123_B", 1, 0 },
{ "123_A", "123_B", 100, 'A'-'B' },
{ "abc\0ABC"s, "abc\0ABZ"s, 6, 0 },
{ "abc\0ABC"s, "abc\0ABZ"s, 7, 'C'-'Z' },
{ std::string(126, '1') + "A", std::string(126, '1') + "B", 10000, -1 },
{ std::string(127, '1') + "A", std::string(127, '1') + "B", 10000, -1 },
{ std::string(128, '1') + "A", std::string(128, '1') + "B", 10000, -1 },
{ std::string(129, '1') + "A", std::string(129, '1') + "B", 10000, -1 },
{ std::string(254, '1') + "A", std::string(254, '1') + "B", 10000, -1 },
{ std::string(255, '1') + "A", std::string(255, '1') + "B", 10000, -1 },
{ std::string(256, '1') + "A", std::string(256, '1') + "B", 10000, -1 },
{ std::string(257, '1') + "A", std::string(257, '1') + "B", 10000, -1 },
};
void test(const char* s1, const char* s2, const int n, const int result) {
const static auto error_message = [](const std::string& function, const char* s1, const char* s2, const int n) -> std::string {
return function + " failed\n"
"Input strings:\n"
" s1: \"" + std::string(s1) + "\"\n"
" s2: \"" + std::string(s2) + "\"\n"
"Length (n): " + std::to_string(n) + "\n";
};
const int std_memcmp_result = memcmp(s1, s2, n);
if (std_memcmp_result != result)
std::cout << error_message("memcmp", s1, s2, n);
EXPECT_EQ(std_memcmp_result, result);
}
TEST(MyMemcmpTest, cases) {
for (const auto& testCase : testCases) {
test(testCase.s1.c_str(), testCase.s2.c_str(), testCase.n, testCase.result);
}
}
添加行后
{ "", "123456789", 5, -'1' }
场景测试
{ "abc\0ABC"s, "abc\0ABZ"s, 7, 'C'-'Z' }
开始给出意想不到的结果:
memcmp
函数返回 -1
,而不是按预期返回第一个不匹配字符(“C”和“Z”)之间的差异。
这是输出:
[ RUN ] MyMemcmpTest.cases
memcmp failed
Input strings:
s1: "abc"
s2: "abc"
Length (n): 7
../test/my_memcmp_test.cpp:96: Failure
Expected equality of these values:
std_memcmp_result
Which is: -1
result
Which is: -23
[ FAILED ] MyMemcmpTest.cases (0 ms)
如果我从 testCases 向量中注释掉任何其他场景,错误就会消失。
我知道 memcmp 在一般情况下不必返回第一个不匹配字符之间的差异。文档仅指定返回值的符号(在 Linux 上)。 但尚不清楚为什么添加或删除一个测试场景会影响另一场景的返回值!他们不应该互相影响!
如果问题出在空终止符上,我会尝试尽可能安全地创建字符串。无论如何,我不明白这会如何影响结果。
您对 memcmp 返回的内容假设太多。
语言规范中没有任何地方规定结果必须是第一个不同字节的值的差异。只有返回值的符号很重要(即是 0、负数还是正数)。
在您的特殊情况下,符合标准的实现可以自由返回-23以及-1甚至-123124。此外,它可以任意改变其行为。内存对齐、大小、编译标志等可能会影响结果。
所以不要指望结果是一个特定的值,而只指望它是更大、更小还是等于 0。