Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中比较char*和string literal?_C_Char_Strcmp_Strncmp - Fatal编程技术网

如何在C中比较char*和string literal?

如何在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

我需要比较一些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 (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
测试char*str=“OK”,而不是注释通过调用
fgets
。那么就没有混乱了。你的问题对其他人来说是清楚的,这一点也很重要。关于提前获得长度。我从串行设备读取这些字符,所以我有一个计数器来计算它们的长度。如果a做了像if(length==2&&memcmp(str,“OK”,3)){…}这样的事情会更快吗?@TertulianoMáximoAfonso。如果长度通常匹配,则速度会变慢,如果长度不匹配,则速度会变快。因为我有很多这样的比较,其中只有一个匹配,我将做这个检查。谢谢;)