C中的memcmp,strcmp和strncmp有啥区别?
Posted
技术标签:
【中文标题】C中的memcmp,strcmp和strncmp有啥区别?【英文标题】:What is the difference between memcmp, strcmp and strncmp in C?C中的memcmp,strcmp和strncmp有什么区别? 【发布时间】:2012-10-17 05:25:24 【问题描述】:我用 C 语言编写了一小段代码来测试 C 语言中的 memcmp()
strncmp()
strcmp()
函数。
这是我写的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
char *word1="apple",*word2="atoms";
if (strncmp(word1,word2,5)==0)
printf("strncmp result.\n");
if (memcmp(word1,word2,5)==0)
printf("memcmp result.\n");
if (strcmp(word1,word2)==0)
printf("strcmp result.\n");
由于我对这三个功能感到困惑,有人可以解释一下它们的区别吗?
我的主要问题是我有一个文件,我在其中标记了它的行,问题是当我标记文件中的“原子”一词时,我必须停止标记过程。
我第一次尝试strcmp()
,但不幸的是,当它到达文件中放置“原子”一词的位置时,它并没有停止而是继续,但是当我使用memcmp()
或@987654328 时@它停止了,我很高兴。
但后来我想,如果有一个字符串的前 5 个字母是 a,t,o,m,s 并且后面跟着其他字母会怎样。
不幸的是,我的想法是正确的,因为我使用上面的代码将word1
初始化为“atomsaaaaa”,word2
初始化为原子,memcmp()
和strncmp()
在 if 语句中返回 0。另一方面手strcmp()
它没有。看来我必须使用strcmp()
。
【问题讨论】:
感谢包含源代码。现在,如果您展示您获得的结果和预期的结果,您的问题会更清楚。 @PascalCuoq 例如,如果我将 word1 初始化为“atomr”,将 word2 初始化为“atoms”,那么当我运行可执行文件时,包含 memcmp() 的 if 语句永远不会为真。 @PascalCuoq.Okay 我找到了问题的答案。 @el10780:不,我的意思是手册页。例如,像这样——kernel.org/doc/man-pages/online/pages/man3/memcmp.3.html 值得注意的是,memcmp 可以快得多,因为它通常被优化为使用单个加载支持的最大类型,并在其中一个地址对齐后立即存储。所以它实际上一次比较多个字符而不是一个,可能是 8 个字符比较,可能至少 4 个。 【参考方案1】:简而言之:
strcmp
比较以 null 结尾的 C 字符串
strncmp
最多比较 N 个以 null 结尾的 C 字符串的字符
memcmp
比较 N 字节的二进制字节缓冲区
所以,如果你有这些字符串:
const char s1[] = "atoms\0\0\0\0"; // extra null bytes at end
const char s2[] = "atoms\0abc"; // embedded null byte
const char s3[] = "atomsaaa";
那么这些结果成立:
strcmp(s1, s2) == 0 // strcmp stops at null terminator
strcmp(s1, s3) != 0 // Strings are different
strncmp(s1, s3, 5) == 0 // First 5 characters of strings are the same
memcmp(s1, s3, 5) == 0 // First 5 bytes are the same
strncmp(s1, s2, 8) == 0 // Strings are the same up through the null terminator
memcmp(s1, s2, 8) != 0 // First 8 bytes are different
【讨论】:
感谢 Adam。您的回答清楚地说明了这三个功能的使用。 表示 memcmp 与 strcmp 类似,只是等于 0 的字节不被视为比较终止符。所以 strcmp 基本上使用了以空字符结尾的字符串的属性。 很好的答案。我只是花了几个小时试图弄清楚为什么比较 24 字节(非空终止)字符串在大约 50% 的时间返回 0 并在其余时间返回一些随机值。 memcmp 绝对是我应该使用的。【参考方案2】:memcmp
比较字节数。
strcmp
之类的比较字符串。
您在示例中有点作弊,因为您知道两个字符串都是 5 个字符长(加上空终止符)。但是,如果您不知道字符串的长度怎么办?这通常是这种情况?好吧,你使用strcmp
因为它知道如何处理字符串,memcmp
不知道。
memcmp
是关于比较字节序列的。如果您知道每个字符串有多长,那么是的,您可以使用memcmp
来比较它们,但这种情况多久发生一次?很少。您经常需要字符串比较函数,因为...它们知道什么是字符串以及如何比较它们。
至于您遇到的任何其他问题,您的问题和代码都不清楚。请放心,尽管strcmp
在一般情况下比memcmp
更适合字符串比较。
【讨论】:
让我换一种方式问。如果我使用 memcmp 并将 word1 初始化为“atomr”并将 word2 初始化为“atoms”会发生什么。它会返回 0 吗? @el10780:这取决于你传递给它的长度。如果您要求memcmp
比较 4 个或更少的字节,那么它将返回 0(等于);如果您要求它比较 5 个或更多字节,那么它将返回非 0(不相等)。
原谅我的无知,但我无法理解“atoms”和“atomr”在字节序列方面的区别。它们确实有相同的大小,对吧?但是“的字节序列” atomr”是 97,116,111,109,114,“atoms”是 97,116,111,109,115。所以对于 memcmp,如果它检查所有五个字符,它不会返回 0。无论如何,感谢您的快速回复和帮助。【参考方案3】:
strcmp():
用于比较存储在两个变量中的两个字符串,比较它们需要一些时间。所以它会减慢这个过程。strncmp():
和上一个非常相似,但是在这个中,它只比较前n个字符。这也会减慢进程。memcmp():
此函数用于使用它们的内存比较两个变量。它不会一一比较它们,它一次比较四个字符。如果你的程序太在意速度,我推荐使用 memcmp()。【讨论】:
-1 因为这是不正确的,并且对这些功能的速度和实现做出了大量毫无根据的假设。 (例如 strcmp 和 strncmp 的速度)(例如执行 memcmp 一次读取单词)。根本没有正确回答问题。 与 Wiz 的论点相反,Arvid 是唯一一个解释 memcmp 相对于 strncmp 的巨大速度优势的人。他只是没有提到对齐优化。大多数编译器中的 memcmp 确实比较的是单词而不是字符。因此它可能会超出导致 valgrind 警告的字符串。您实际上不需要解释缓冲区与字符串的区别。 试图争论这种差异是荒谬的。 memcmp 和 strcmp 与现代 libcs 的唯一区别是 strcmp 必须检查它是否必须停止,这比仅比较字节需要更多时间。我个人对此进行了基准测试,仅测量了 memcmp 和 strcmp 之间的速度差异约为 10%【参考方案4】:strncmp 和 memcmp 是相同的,只是前者负责以 NULL 结尾的字符串。
【讨论】:
【参考方案5】:对于 strcmp,您只想比较您知道将是字符串的内容,但有时情况并非总是如此,例如读取二进制文件的行,您可能希望使用 memcmp 来比较某些行包含 NUL 字符但匹配的输入,您可能希望继续检查输入的更多长度。
【讨论】:
【参考方案6】:总结一下:
strncmp() 和 strcmp() 将 0 字节视为字符串的结尾,超出它的范围不进行比较
对于memcmp(),0字节没有特殊意义
【讨论】:
以上是关于C中的memcmp,strcmp和strncmp有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
字符串函数---strcmp()与strncmp()详解及实现
玩转C语言库函数。包含strlenstrcpystrcmpstrcatmemcmpmemmovestrstr等等常用的库函数
玩转C语言库函数。包含strlenstrcpystrcmpstrcatmemcmpmemmovestrstr等等常用的库函数