我在C中创建了这个类(参见Class in C (not C++)),我想这样做:
void assignModel(Car *this, char *model)
{
// Is a string, so I need null all the space
memcpy(this->model, '\0', sizeof(this->model)); // Error in execution time
strncpy(this->model, model, strlen(model)); // Yes, it's insecure :)
}
答案 0 :(得分:2)
memcpy
期望第二个参数指向要从中获取数据的内存中的某个位置。 '\0'
并未指向记忆:当它转换为void*
时,它变为NULL
。解除引用NULL
会导致未定义的行为,因此会出现执行时错误。
如果您想将零设置为特定字段,请使用memset
代替memcpy
:
memset(this->model, 0, sizeof(this->model)); // this->model is an array
但是,在您的情况下,不需要用零填充数组:如果正确复制字符串,则不必填充零来获取终结符。这是问题 - 当你这样做时,
strncpy(this->model, model, strlen(model));
null终止符不写入this->model
数组,使字符串无法终止。您的代码用于"补偿"通过用零预填充数组来解决这个缺点。但是,当strlen(model)
与您可以写入this->model
数组的字符总数相同时,这会使字符串无法终止。
要解决此问题,如果您的系统提供它,我会使用strlcpy
(小心 - 它不是C标准的一部分)。
strlcpy(this->model, model, sizeof(this->model));
如果您的系统没有,您可以按如下方式模拟其效果:
int len = min(sizeof(this->model)-1, strlen(model));
memcpy(this->model, model, len);
this->model[len] = '\0';
编辑:感谢所有对此发表评论的人!
答案 1 :(得分:0)
这是一种更好的方法(我认为)你想做的事情:
void assignModel(Car * const this, const char * const model)
{
snprintf(this->model, sizeof(this->model), "%s", model);
}
这有一些优点:
strcpy()
不同)strncpy())
不同,它仍然具有'\ 0'终结符。memset()
。strlen()
。const
,因此编译器会捕获一些愚蠢的错误,比如混淆源和目标。在大多数情况下,
snprintf(foo, sizeof(foo), ...)
行为比strcpy()
或strncpy()
更好。