strncmp优于strcmp的优势?

Tho*_*son 11 c c-standard-library

似乎strncmp通常建议比strcmp,有什么优势?我认为这可能与安全有关.如果是这种情况,如果已知其中一个输入字符串是字面常量,它仍然适用"LiteralString"吗?

更新: 我的意思是在需要比较整个字符串的相同用户场景下,strncmp可以如下使用.我想知道它是否有意义.

strncmp(inputString, "LiternalString", strlen("LiternalString"));
Run Code Online (Sandbox Code Playgroud)

Sur*_*ati 19

问题strcmp在于,有时,如果错误地,传递的参数不是有效的C字符串(意味着p1或p2不以空字符终止,即不以NULL结尾的字符串),那么,strcmp继续比较直到它到达不可访问的内存和崩溃或有时导致意外的行为.

使用strncmp您可以限制搜索,以便它不会到达不可访问的内存.

但是,从那以后不应该说这strcmp是不安全的.这两种功能都非常适合它们的工作方式.程序员man在使用之前应该读取该函数的页面,并且在将参数传递给这样的库函数时必须足够真诚.

您还可以阅读包含几乎相似问题的THIS.

  • 整个"如果错误"的想法并不令人信服.`strncmp`不是强化函数.它在语义上与`strcmp`不同,并且具有不同的用途. (3认同)

R..*_*R.. 12

strncmp没有"优势strcmp"; 而是他们解决不同的问题.strcmp用于确定两个字符串是否相等(如果不相同,可能如何相对于彼此对它们进行排序/排序).strncmp(主要)用于确定字符串是否以特定前缀开头.例如:

if (strncmp(str, "--option=", 9)==0)
Run Code Online (Sandbox Code Playgroud)

将确定是否str"--option=".开头.如果不strcmp修改要检查的字符串(可能不是有效的操作)或制作无用的副本,就无法实现这一点.memcmp除非你已经知道str一个对象的长度至少为9个字节,否则它也无法实现; 否则调用memcmp会有未定义的行为.

还有其他用例strncmp,例如使用非C字符串数据.


Som*_*ude 8

这一切都取决于你的用例.使用strncmp,如果你只需要比较字符固定数量,使用strcmp,如果你需要比较整个字符串.

就是这样.

  • @chqrlie是的,但是必须注意确保子字符串不长于完整字符串. (3认同)

chu*_*ica 5

...在需要比较整个字符串的相同用户场景下,...

 strncmp(inputString, "LiternalString", strlen("LiternalString"));
Run Code Online (Sandbox Code Playgroud)

inputString考虑字符串比字符串文字长的情况。

const char *inputString = "LiternalString_XYZ";
int cmp = strncmp(inputString, "LiternalString", strlen("LiternalString"));
printf("%d\n", cmp); // prints 0.
Run Code Online (Sandbox Code Playgroud)

但OP想要比较整个字符串

const char *inputString = "LiternalString_XYZ";
int cmp = strcmp(inputString, "LiternalString");
printf("%d\n", cmp); // prints non-zero.
Run Code Online (Sandbox Code Playgroud)

OP直接问题的结论

我想知道这是否有意义。

不。要比较整个字符串strncmp()无法始终提供正确的结果。使用strcmp()


更远

strncmp(s1,s2,n)可以限制搜索,以便在正确计算的情况下 n它不会到达不可访问的内存- 这在OP的代码中没有完成,并且当和 的最佳n值不同时,正确执行会出现问题。s1s2

大小限制n适用于两者s1s2因此使该函数可用于比较前缀,但不“更安全”。

在OP的情况下,由于字符串文字的字符串长度,没有理由因为“安全”而限制搜索,因为字符串文字 始终包含终止空字符

如果有的话,n应该是基于 的某些属性inputString

类似的代码strncmp(s1, string_literal, strlen(s1))在功能上不正确,因为比较错过了空字符。稍微好一点的是strncmp(s1, string_literal, strlen(s1)+1),但这在功能上与更简单的相同,strcmp(s1, string_literal)并且“安全性”没有降低。


下面提供了一些改进的“安全性”,以防foo()没有正确形成 字符串N != M,但如果如上所述,可能会提供错误的答案。

char s1[N];
foo(s1); // populate s1 somehow
int cmp = strncmp(s1, string_literal, sizeof s1);

char s1[N];
char s2[M];
foo(s1); // populate s1 somehow
foo(s2); // populate s2 somehow
int cmp = strncmp(s1, s2, min(sizeof s1, sizeof s2));
Run Code Online (Sandbox Code Playgroud)

但在这些情况下,问题出在foo(),而不是这里。
对我来说,如果foo()有如此疑问,我会使用以下内容

s1[sizeof s1 - 1] = '\0';
s2[sizeof s2 - 1] = '\0';
int cmp = strcmp(s1, s2);
Run Code Online (Sandbox Code Playgroud)

或检测foo()未形成字符串

char s1[N];
foo(s1);
if (memchr(s1, '\0', sizeof s1) == NULL) Oops();
Run Code Online (Sandbox Code Playgroud)

这个故事的寓意是:strncmp()不是“更安全”的版本strcmp()。它是一个用于不同工作的工具:比较字符串前缀。