这个测试实际上通过了,似乎目标的大小无关紧要,只要它是指向字符数组的有效指针即可。
我实际上预计测试会失败,任何解释将不胜感激。
#include "gtest/gtest.h"
#include <string>
using namespace std;
TEST(practice, book) {
const char * copyFrom = "Hello World!";
char copyTo[0]; //TODO: why it works?
std::strcpy(copyTo, copyFrom);
EXPECT_STREQ("Hello World!", copyTo);
std::cout << copyTo << std::endl;
}
我实际上预计测试会失败
为什么?
任何类型的失败都意味着以下两件事之一:
-
由于未定义的行为而崩溃
-
std::strcpy
引发的其他错误对其参数进行了一些检查
std::strcpy
不会对其参数执行任何检查(由于性能原因),并且它明确指出尝试使用它写入不够大的缓冲区是未定义的行为。这意味着崩溃(或其他故障迹象)也可能发生,但由于未定义的行为,而不是由于某些确定缓冲区不正确的诊断。
[...]似乎目的地的大小无关紧要,只要它是指向char数组的有效指针即可。
要编译和运行代码?是的。为了使代码格式正确?没有。
您的代码表现出未定义的行为,并且无法预测其结果。它可能看起来有效,它可能崩溃,它似乎只在星期五工作,或者它可以开始无限地输出东西到标准输出。
请记住 - 你不能期望从表现出未定义行为的代码中获得任何东西。
它不起作用。或者也许确实如此。未定义行为(UB)就是这样,允许任何事情发生。
无论如何,原始数组必须具有正大小,这是引入std::array
的原因之一。如果您的编译器允许零大小的数组作为扩展,则这超出了标准。
不过,假设一个零大小的数组确实有 0 个元素,访问任何成员都是 UB。
由于std::strcpy()
盲目地相信第二个参数指向一个字符串,而第一个参数指向一个足够大小的缓冲区来存储包含终止 null 的副本,因此您显然正在写入超过零个元素。
顺便说一句,您必须包括<cstring>
,并且不应该using namespace std;
。