C语言 strncmp 相对于 strcmp 的优势?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30190460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:56:27  来源:igfitidea点击:

Advantages of strncmp over strcmp?

cc-standard-library

提问by Thomson

Seems strncmpis usually recommended than strcmp, what are the advantages? I think it could be related to security. If this is the case, is it still applicable if one of the input string is known to be literal constant, like "LiteralString"?

好像strncmp是比较推荐的strcmp,有什么好处呢?我认为这可能与安全有关。如果是这种情况,如果已知输入字符串之一是文字常量,它是否仍然适用,例如"LiteralString"

UPDATE:I mean under the same user scenario where whole strings need to be compared, and strncmpcan be used as below. I am wondering it makes sense or not.

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

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

回答by Surajeet Bharati

The problem with strcmpis that sometimes, if by mistake, arguments that are passed are not valid C-strings (meaning that p1 or p2 is not terminated with a null character i.e. not NULL-terminated String), then, strcmp continues comparing until it reaches non-accessible memory and crashes or sometimes results to an unexpected behaviour.

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

Using strncmpyou can limit the search, so that it doesn't reach non-accessible memory.

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

But, from that it should not be concluded that strcmpis insecure to use. Both the functions works well in the way they are intended to work. Programmer should read manpage for that function before using it and must be sincere enough when passing parameters to such library functions.

但是,从中不应得出strcmp使用不安全的结论。这两个功能都以预期的方式运行良好。程序员man在使用该函数之前应该阅读该函数的页面,并且在向此类库函数传递参数时必须足够真诚。

You can also read THISwhich contains an almost similar question.

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

回答by R.. GitHub STOP HELPING ICE

strncmpdoes not have "advantages over strcmp"; rather they solve different problems. strcmpis for determining if two strings are equal (and if not, possibly how to order/sort them with respect to each other). strncmpis (mainly) for determining whether a string begins with a particular prefix. For example:

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

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

will determine if strbegins with "--option=". This cannot be achieved by strcmpwithout either modifying the string to be checked (which may not be a valid operation) or making a useless copy of it. It also cannot be achieved with memcmpunless you already know strpoints to an object at least 9 bytes in length; otherwise the call to memcmpwould have undefined behavior.

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

There are other usage cases for strncmptoo, such as working with non-C-string data.

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

回答by Some programmer dude

It all depends on your use-cases. Use strncmpif you only need to compare a fixed number of characters, use strcmpif you need to compare a whole string.

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

That's about it.

就是这样。

回答by user3099889

Just post an anti-strncmp use case here. Think about the following code.

只需在此处发布反 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;
}

回答by user9455050

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 '
 strncmp(inputString, "LiternalString", strlen("LiternalString"));
'

assume: dev1 is null terminated and dev2 is probably not. ret1 = 0 (false positive result), rather than ret2=-1 (valid result)

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

fazit: strncmp is not just a safer way for strcmp. depends on how you make use of it.

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

i′d use strcmp on strings, and strncmp on substring search.

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

回答by chux - Reinstate Monica

... under the same user scenario where whole stringsneed to be compared, ...

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

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

Consider the case where string inputStringis longer than the string literal.

考虑 stringinputStringstring literal长的情况。

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

But OP wanted whole stringscompared.

但是 OP 想要比较整个字符串

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));


Conclusion to OP's direct question

OP直接问题的结论

I am wondering it makes sense or not.

我想知道这是否有意义。

No. To compare whole strings, strncmp()fails to consistently provide the correct result. Use strcmp().

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



Further

更远

strncmp(s1,s2,n)can limit the search, so that it doesn't reach non-accessible memory ifnwas properly computed - which was not done in OP's code and problematic to do right when the best nis different for s1and s2.

strncmp(s1,s2,n)可以限制搜索,所以它没有达到不可访问的内存,如果n被正确地计算-这是不是在OP的代码完成和问题做对的时候最好n是不同的s1s2

The size limit napplies to both s1and s2thus making this function useful for comparing prefixes, but not `"safer".

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

In OP's case, there is no reason to limit the search due to "safety" on account of the string length of the string literalas string literalsalwayscontains a terminating null character.

在OP的情况下,没有理由将搜索限制,由于是考虑到的字符串长度的“安全”字符串文字作为字符串字面量总是包含终止空字符

If anything, nshould have been based on some property of inputString.

如果有的话,n应该基于inputString.

Code like strncmp(s1, string_literal, strlen(s1))is functionally incorrect as the compare misses the null character. A wee bit better is strncmp(s1, string_literal, strlen(s1)+1), but that is functionally the same as the simpler strcmp(s1, string_literal)with no reduction in "safety".

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



The below offer some improve "safety" in case foo()did not properly form strings, but can provide the wrong answer if N != Mas above.

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

s1[sizeof s1 - 1] = '
char s1[N];
foo(s1);
if (memchr(s1, '##代码##', sizeof s1) == NULL) Oops();
'; s2[sizeof s2 - 1] = '##代码##'; int cmp = strcmp(s1, s2);

Yet in those cases, the problem is in foo(), not here.
For me, if foo()was so questionable, I'd use the following

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

##代码##

or detect that foo()did not form a string.

或者检测到foo()没有形成字符串

##代码##

Moral of the story: strncmp()is not a "safer" version of strcmp(). It is a tool for a different job: comparing string prefixes.

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

回答by M.L.

strcmp could lead to storage volation and segmentation fault in case where one of arguments is not null-terminated string. Take a look why you should use strncpy instead of strcpy. Consequences are unlikely to happen in strcmp, but issue is the same. strnxxx function family try to prevent reading/writing not acquired memory.

如果参数之一不是以空字符结尾的字符串,strcmp 可能会导致存储波动和分段错误。看看为什么你应该使用 strncpy 而不是 strcpy。在 strcmp 中不太可能发生后果,但问题是相同的。strnxxx 函数族尽量防止读/写未获得的内存。

Disadvantage of using strn is extra compare and decrement operation on counter.

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

In few words: strncmp is safer then strcmp, but it is slower too.

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

回答by nishant naveen

I could see only one advantage, that strncmp will take slightly less time to execute than strcmp as we will always compare prefix of string to comapre rather than entire string.

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

I don't think that there is any security aspect involved in strcmp and strncmp algorithm. They are same except that in strncmp only first 'n' characters are compared.

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

回答by Miguel13366

strncmp is more secure than strcmp

strncmp 比 strcmp 更安全

same as strncpy and strcpy or strlen and strnlen, because strcmp compares until first zeroterminator is found. strncmp compares until first zeroterminator but maximum n characters. So if your string has a defined length it is better to use the strn*-functions.

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

See also

也可以看看

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

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