strncmp优于strcmp的优势?

时间:2015-05-12 12:10:07

标签: c c-standard-library

通常建议使用strncmp而不是strcmp,有什么好处?我认为这可能与安全有关。如果是这种情况,如果已知其中一个输入字符串是文字常量,如"LiteralString"

,它是否仍然适用

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

strncmp(inputString, "LiternalString", strlen("LiternalString"));

9 个答案:

答案 0 :(得分:19)

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

使用strncmp,您可以限制搜索,以便它无法访问不可访问的内存。

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

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

答案 1 :(得分:11)

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

if (strncmp(str, "--option=", 9)==0)

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

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

答案 2 :(得分:8)

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

就是这样。

答案 3 :(得分:0)

在这里发布一个反strncmp用例。 想想以下代码。

#include <stdio.h>
#include <dirent.h>

int main()
{
    //I want to list all files under current folder, include hidden files.
    DIR *dir;
    struct dirent *dp;
    char * file_name;
    dir = opendir(".");
    while ((dp=readdir(dir)) != NULL) {
        printf("debug: %s\n", dp->d_name);
        if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") )
        //It doesn't work if you replace strcmp with strncmp here.
        //if ( !strncmp(dp->d_name, ".", 1) || !strncmp(dp->d_name, "..", 2) )  
        {
        } else {
            file_name = dp->d_name;
            printf("file_name: \"%s\"\n",file_name);
        }
    }
    closedir(dir);
    return 0;
}

答案 4 :(得分:0)

int ret1, ret2;
char dev1[]  = { "ABC" };
char dev2[4] = { "ABC" };

dev2[3] = 'D';
ret1 = strncmp(dev1,dev2,strlen(dev1));  // # of characters
ret2 = strncmp(dev1,dev2,sizeof(dev1));  // # of characters plus '\0'

假设:dev1为空终止,dev2可能不是。 ret1 = 0(假阳性结果),而不是ret2 = -1(有效结果)

fazit:strncmp不仅仅是strcmp更安全的方式。取决于你如何使用它。

我会在字符串上使用strcmp,在子字符串搜索上使用strncmp。

答案 5 :(得分:0)

  

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

 strncmp(inputString, "LiternalString", strlen("LiternalString"));

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

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

但是OP希望整个字符串进行比较。

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

对OP直接问题的结论

  

我想知道这是否有意义

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


进一步

strncmp(s1,s2,n)可以限制搜索,从而不会到达不可访问的内存如果 n得到了正确的计算-这在OP的代码中没有完成并且存在问题当ns1的最佳s2不同时正确地做。

大小限制n既适用于s1,也适用于s2,因此,此功能可用于比较前缀,而不是“更安全”。

在OP的情况下,由于 string文字作为 string文字 ,由于“安全性”,没有理由限制搜索总是包含一个终止的空字符

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

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


如果foo()不能正确形成 strings ,下面提供一些改进的“安全性”,但是如果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));

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

s1[sizeof s1 - 1] = '\0';
s2[sizeof s2 - 1] = '\0';
int cmp = strcmp(s1, s2);

或检测到foo()没有形成 string

char s1[N];
foo(s1);
if (memchr(s1, '\0', sizeof s1) == NULL) Oops();

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

答案 6 :(得分:-1)

如果其中一个参数不是以空字符结尾的字符串,则strcmp可能会导致存储语音和分段错误。看看why you should use strncpy instead of strcpy。在strcmp中不太可能发生后果,但问题是相同的。 strnxxx函数系列试图阻止读/写未获取的内存。

使用strn的缺点是在计数器上进行额外的比较和减少操作。

简而言之:strncmp比strcmp更安全,但它也更慢。

答案 7 :(得分:-2)

我只能看到一个优点,即strncmp执行的时间比strcmp少一些,因为我们总是将字符串的前缀与comapre比较,而不是整个字符串。

我认为strcmp和strncmp算法不涉及任何安全方面。它们是相同的,除了在strncmp中只比较第一个'n'字符。

答案 8 :(得分:-4)

strncmp比strcmp

更安全

与strncpy和strcpy或strlen和strnlen相同,因为strcmp会比较,直到找到第一个zeroterminator。 strncmp比较直到第一个zeroterminator但最多n个字符。因此,如果您的字符串具有定义的长度,则最好使用strn * -functions。

另见

http://www.cplusplus.com/reference/cstring/strncmp/?kw=strncmp