7

据我了解,strcmp()(没有“n”)在任一参数中看到空字符后,会立即停止处理并返回结果。
因此,如果 100% 确定其中一个参数是空终止的(例如,它是一个字符串文字),那么使用(with 'n')和strncmp()调用strlen()参数将比较限制为已知字符串长度,因为strcmp()将永远不会读取比该已知终止字符串中更多的字符。

事实上,在我看来,strncmp()其长度参数是strlen()前两个参数之一的调用与这种情况的不同之处在于,它通过评估表达式strcmp()来浪费与已知终止字符串的大小成线性关系的时间。strlen()

考虑:

示例代码 A:

if (strcmp(user_input, "status") == 0)
    reply_with_status();

示例代码 B:

if (strncmp(user_input, "status", strlen("status")+1) == 0)
    reply_with_status();

前者比后者有什么好处吗?因为我经常在其他人的代码中看到

我对这些功能的工作原理有错误的理解吗?

4

6 回答 6

5

在您的特定示例中,我会说使用它是有害的,strncmp因为:

  • 仍然使用strlen扫描
  • 重复字符串文字"status"
  • 加 1 以确保字符串确实相等

user_input所有这些都增加了混乱,如果它确实短于 6 个字符并且包含与测试字符串相同的字符,那么在任何情况下都不会防止溢出。

那将是例外。如果您知道输入字符串的内存总是比测试字符串中的字符数多,请不要担心。否则,您可能需要担心,或者至少考虑一下。 strncmp对于测试大缓冲区内的东西很有用。

我的偏好是代码可读性。

于 2013-02-14T22:19:33.357 回答
4

是的,它确实。如果在 strncmp 中使用 strlen,它将遍历指针,直到在字符串中看到 null。这使得它在功能上等同于 strcmp。

于 2013-02-14T22:13:42.047 回答
4

在您给出的特定情况下,它确实没用。然而,轻微的改变更常见:

if (strncmp(user_input, "status", strlen("status")) == 0)
    reply_with_status();

这个版本只检查是否user_input 以 开头"status"所以它有不同的语义。

于 2013-02-14T22:27:43.613 回答
2

除了检查字符串开头是否与输入匹配的技巧之外,strncmp 只有在您不能 100% 确定字符串在其分配空间结束之前是否以空结尾时才会有用。

所以,如果你有一个固定大小的缓冲区,你可以使用你的用户输入:

strncmp(user_input, "status", sizeof(user_input))

因此确保您的比较不会溢出。

但是在这种情况下,您必须小心,因为如果您的 user_input 不是以 null 终止的,那么它确实会检查 user_input 是否与状态的开头匹配。

更好的方法可能是说:

if (user_input[sizeof(user_input) - 1] != '\0') {
  // handle it, since it is _not_ equal to your string
  // unless filling the buffer is valid
}
else if (strcmp(user_input, "status")) { ... }
于 2013-03-07T21:35:01.710 回答
0

现在,我同意这不是 strncmp() 的特别有用的用法,而且我看不出它比 strcmp() 有什么好处。

但是,如果我们通过删除+1after来更改代码strlen,那么它就开始有用了。

 strncmp(user_input, "status", strlen("status"))

因为这会将前 6 个字符user_input与“状态”进行比较——这至少有时是有意义的。

因此,如果+1存在,它将成为常规strcmp- 计算长度只是浪费时间。但如果没有+1,这是一个非常有用的比较(在适当的情况下)。

于 2013-02-14T22:27:13.967 回答
0

strncmp() 的用途有限。如果在两个字符串中的任何一个上遇到 NUL,正常的 strcmp() 将停止。(在这种情况下字符串不同) Strncmp() 将停止并返回零(“字符串在前 N 个字符中相等”)

stncmp() 的一种可能用途是解析选项,直到非重要部分,例如

if (!strncmp("-st", argv[xx], 3)) {}

,对于“-string”或“-state”或“-st0”将返回零,但对于“-sadistic”则不会

于 2013-02-14T22:32:22.727 回答