ZetCode

C strncmp 函数

最后修改:2025 年 4 月 8 日

字符串比较是 C 编程的基础,而 strncmp 是安全比较字符串的关键函数。本教程将深入介绍 strncmp,包括其语法、用法以及相对于 strcmp 的优势。我们将探讨实际示例并讨论安全注意事项。理解 strncmp 有助于通过防止字符串比较期间的缓冲区溢出来编写更安全的代码。

什么是 strncmp?

strncmp 函数将两个字符串最多指定数量的字符进行比较。它在 string.h 中声明,并接受三个参数:两个字符串指针和一个最大比较长度。与 strcmp 不同,它不会读取超出指定限制的地方,因此对于不受信任的输入更安全。对于相等的字符串,它返回零;如果第一个字符串小于,则返回负数;如果大于,则返回正数(按字典顺序)。

基本的 strncmp 用法

此示例演示了使用 strncmp 进行基本的字符串比较。

basic_compare.c
#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "Hello";
    char str2[] = "Hello, World!";
    
    // Compare first 5 characters
    int result = strncmp(str1, str2, 5);

    if (result == 0) {
        printf("First 5 characters are equal\n");
    } else {
        printf("First 5 characters are different\n");
    }

    return 0;
}

在这里,strncmp 仅比较两个字符串的前 5 个字符。比较是区分大小写的,并在第一个不同的字符处或达到指定长度时停止。此示例演示了如何在不冒缓冲区溢出风险的情况下安全地比较字符串前缀。由于两个字符串都以“Hello”开头,因此结果为零。

比较固定长度字符串

strncmp 非常适合比较固定长度的字符串或缓冲区,如下所示。

fixed_length_compare.c
#include <stdio.h>
#include <string.h>

int main() {
    char password[8] = "secret";
    char input[8] = "secrets";
    
    // Compare exactly 8 bytes (buffer size)
    int match = strncmp(password, input, sizeof(password));

    if (match == 0) {
        printf("Access granted\n");
    } else {
        printf("Access denied\n");
    }

    return 0;
}

此示例会完整比较两个固定大小的缓冲区,包括任何填充字节。比较使用 sizeof 获取确切的缓冲区大小。此方法可防止在使用以 null 结尾的字符串进行比较时可能发生的时序攻击。请注意,对于安全关键代码,专门的比较函数可能更好。

不区分大小写的比较

此示例演示了使用 strncasecmp 进行不区分大小写的比较。

case_insensitive.c
#include <stdio.h>
#include <strings.h> // For strncasecmp

int main() {
    char str1[] = "HELLO";
    char str2[] = "hello";
    
    // Case-insensitive compare first 5 chars
    int result = strncasecmp(str1, str2, 5);

    if (result == 0) {
        printf("Strings are equal ignoring case\n");
    } else {
        printf("Strings are different\n");
    }

    return 0;
}

strncasecmp(在 Windows 上为 _strnicmp)执行不区分大小写的比较,最多指定长度。这对于不区分大小写的匹配同时保持长度安全很有用。该函数在类 Unix 系统上声明在 strings.h 中。请注意,区域设置可能会影响大小写转换规则。

比较子字符串

此示例展示了如何使用 strncmp 和指针算术来比较子字符串。

substring_compare.c
#include <stdio.h>
#include <string.h>

int main() {
    char text[] = "The quick brown fox";
    char search[] = "quick";
    
    // Compare substring starting at position 4
    int found = strncmp(text + 4, search, strlen(search));

    if (found == 0) {
        printf("Substring found\n");
    } else {
        printf("Substring not found\n");
    }

    return 0;
}

在这里,我们将 text 中从位置 4 开始的子字符串与 search 字符串进行比较。指针算术(text + 4)移动到所需的起始位置。此技术对于解析和搜索字符串很有用。始终确保子字符串长度不超过剩余字符串长度,以避免未定义行为。

安全字符串比较带长度检查

此示例演示了一种更安全的比较,首先检查字符串长度。

safe_compare.c
#include <stdio.h>
#include <string.h>

int safe_str_compare(const char *s1, const char *s2, size_t max_len) {
    size_t len1 = strnlen(s1, max_len);
    size_t len2 = strnlen(s2, max_len);
    
    if (len1 != len2) return 1; // Different lengths
    return strncmp(s1, s2, max_len);
}

int main() {
    char input1[20] = "password";
    char input2[20] = "password123";
    
    if (safe_str_compare(input1, input2, sizeof(input1)) {
        printf("Strings are different\n");
    } else {
        printf("Strings are equal\n");
    }

    return 0;
}

此示例结合了 strnlenstrncmp 以进行更可靠的比较。辅助函数首先检查字符串在限制内的长度是否相等。这可以防止在长度不同时将部分匹配视为相等。strnlen 函数确保我们不会读取超出指定最大长度的内容,从而增加了另一层安全性。

使用 strncmp 的最佳实践

来源

C strncmp 文档

本教程介绍了 strncmp 函数,从基本用法到高级安全注意事项。尽管简单,但正确的字符串比较对于 C 程序中的安全性和正确性至关重要。始终优先使用 strncmp 等长度受限的函数,而不是其无限制的对应函数。

作者

我的名字是 Jan Bodnar,我是一名敬业的程序员,对编码充满热情。自 2007 年以来,我通过 1,400 多篇文章和 8 本电子书分享了我的专业知识。凭借十多年的教学经验,我致力于使编程易于访问且引人入胜。

列表 C 标准库