strncpy_s 使用 G++ 编译器

strncpy_s using G++ compilers

我最初使用 Microsoft/visual c++ 编译器编写作业,但我的课程要求我 运行 并使用 G++

在 unix 上编译

但是,strncpy_s 不使用 g++ 进行编译,我的特定程序有什么解决方法吗?

这是使用它的代码片段:

void PhoneNumber::setName(const char name[])
{
    strncpy_s(_name, name, MAX_NAME_LENGTH);
}

您不应使用 strncpy 或其 _s 版本 it may be quite surprising in its behaviour

改用strlcpy,参见strlcpy and strlcat - consistent, safe, string copy and concatenation

*_s 函数是 Microsoft 的巧妙尝试,"securing" C 运行时库的字符串函数。这些函数甚至进入了 C99 的附录 K。在撰写本文时,它们尚未在 Linux' glibc 中实现。如果你绝对必须(我建议不要这样做),只需正确使用普通的 C 库函数(这意味着到处都没有幻数和适当的缓冲区大小),是的,这很麻烦。

这可能会或可能不会在您的作业上下文中使用,但它确实是唯一正确的答案:

class PhoneNumber
{
private:
  std::string name;
  // ...
public:
  void setName(std::string name);
  //...
};

void PhoneNumber::setName(std::string name)
{
  this->name = std::move(name); // 'this->' is optional, but clarifies without resorting to some clever renaming of the variables
}

或者,完全删除 setter:

struct PhoneNumber
{
  std::string name;
  // ...
};

并直接分配成员。但是这种编码风格,虽然非常理智,但可能会让你被老师大吼大叫。

不要在 C++ 中使用 C 字符数组。你会无缘无故搬起石头砸自己的脚。它也摆脱了代码中的幻数,这总是一个加号。


微小的 C++11 和更高版本的模板 wankery。实现 setter 的理想解决方案是使用模板,这样如果 setter 像 setName(std::move(some_string)):

这样调用,就可以避免潜在的代价高昂的双重移动
template<typename T>
void setName(T&& name) { this->name = std::forward<T>(name); }

这将允许任何 assignable/moveable 到 std::string 的内容被接受,这实际上非常好。作为一个额外的好处,您可以获得自动为您选择的最佳代码路径。当然,对于你的作业来说,这将是巨大的矫枉过正,但如果你花时间学习这些概念,你可能只是教老师一些东西。再说一次,更喜欢 public 成员而不是这个模板……太虚伪了,因为这就是它。