如何在C中比较char*和string literal?
我需要比较一些char*(我知道它的长度)和一些字符串文本。现在我是这样做的:如何在C中比较char*和string literal?,c,char,strcmp,strncmp,C,Char,Strcmp,Strncmp,我需要比较一些char*(我知道它的长度)和一些字符串文本。现在我是这样做的: void do_something(char * str, int len) { if (len == 2 && str[0] == 'O' && str[1] == 'K' && str[2] == '\0') { // do something... } } void do_something(char * str, int len) { if
void do_something(char * str, int len) {
if (len == 2 && str[0] == 'O' && str[1] == 'K' && str[2] == '\0') {
// do something...
}
}
void do_something(char * str, int len) {
if (len == 2 && strncmp(str, "OK", len) == 0) {
// do something...
}
}
问题是,我有很多这样的比较要做,把每一个比较分开并键入是相当乏味的。而且,这样做很难维护,也很容易引入bug
我的问题是,是否有速记来键入此内容(可能是宏)。
我知道有strncmp
,我已经看到了。因此,如果速记是使用strncmp
,如下所示:
void do_something(char * str, int len) {
if (len == 2 && str[0] == 'O' && str[1] == 'K' && str[2] == '\0') {
// do something...
}
}
void do_something(char * str, int len) {
if (len == 2 && strncmp(str, "OK", len) == 0) {
// do something...
}
}
然后,我想知道第二个示例与第一个示例具有相同(或更好)的性能。是的但是,您的代码没有将char*
与字符串文字进行比较。它正在比较两个字符串文本。编译器足够聪明,可以发现这一点并优化所有代码。仅保留if
块中的代码
我们可以通过查看comiler生成的汇编代码看到这一点:
cc -S -std=c11 -pedantic -O3 test.c
首先使用原始代码
#include <stdio.h>
#include <string.h>
int main() {
unsigned int len = 2;
char * str = "OK";
if (len == 2 && strncmp(str, "OK", len) == 0) {
puts("Match");
}
}
这两个部件文件实际上是相同的。没有字符串的痕迹,只有放置了
#include <stdio.h>
#include <string.h>
int main() {
//unsigned int len = 2;
//char * str = "OK";
//if (len == 2 && strncmp(str, "OK", len) == 0) {
puts("Match");
//}
}
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 10, 14 sdk_version 10, 14
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
leaq L_.str(%rip), %rdi
callq _puts
xorl %eax, %eax
popq %rbp
retq
.cfi_endproc
## -- End function
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "Match"
.subsections_via_symbols
这是一个注重优化的糟糕地方。字符串与小字符串的比较不太可能是性能问题 此外,您提出的优化可能较慢。您需要获得输入字符串的长度,这需要遍历输入字符串的全长。也许你出于其他原因需要这样做,但这是一个越来越边缘的情况
而
strncmp
可以在看到不相等的字符时立即停止。而且它肯定只需要读到最小字符串的末尾。您的示例意味着您的字符串总是以NUL结尾。在这种情况下,不要费心提前获取它们的长度,因为这涉及到搜索NUL。相反,你可以这样做
memcmp(str, "OK", 3);
这样,NUL也可以进行比较。如果长度大于2,则结果将大于0,如果长度较短,则结果将小于0
这是一个单一的函数调用,memcmp
实际上保证比手工编写的代码得到更好的优化。同时,除非您发现这段代码是一个瓶颈,否则不要麻烦优化。请记住,我在我的机器上运行的任何基准都不一定适用于您的机器
进行此更改的唯一真正原因是为了可读性。第二个示例不应编译,因为
strncmp
采用了未传入的长度参数。已修复。非常感谢。在第二种情况下,如果您需要检查长度,那么您可以使用strcmp
(而不是strncmp
),这将隐含地执行该操作,而不需要len==2
测试如果你知道两个字符串都以null结尾,那么让编译器只使用strcmp进行可能的优化。这是因为你假设我在编译时知道str。这个例子只是为了说明这个问题。str不是在编译时设置的。它来自一个用户。然后我“解析”它以了解适当的操作。@TertulianoMáximoAfonso请提供一个更清楚的示例。我认为它非常清楚。你就是那个告诉我这个例子是我的整个程序并编译了整个程序的人。这是一个非常糟糕的假设。一个例子就是一个例子。不管怎样,我给问题加了一个注释。@TertulianoMáximoAfonso如果你想得到好的答案,你必须提供一个清楚的例子,说明我们正在处理的问题。你必须努力使你的问题尽可能清楚。例如,可以替换为char*str=“OK”,而不是注释代码>通过调用fgets
。那么就没有混乱了。你的问题对其他人来说是清楚的,这一点也很重要。关于提前获得长度。我从串行设备读取这些字符,所以我有一个计数器来计算它们的长度。如果a做了像if(length==2&&memcmp(str,“OK”,3)){…}这样的事情会更快吗?@TertulianoMáximoAfonso。如果长度通常匹配,则速度会变慢,如果长度不匹配,则速度会变快。因为我有很多这样的比较,其中只有一个匹配,我将做这个检查。谢谢;)