C memchr 函数
最后修改:2025 年 4 月 8 日
内存操作在 C 编程中是基础的,而 memchr
是在内存块中搜索字符的关键函数。本教程将深入介绍 memchr
,包括其语法、用法和潜在的陷阱。我们将探讨实际示例,并讨论对关键应用更安全的替代方案。理解 memchr
有助于在维护程序安全性和可靠性的同时高效地搜索内存。
什么是 memchr?
memchr
函数在内存块中搜索字符的第一次出现。它声明在 string.h
中,并接受三个参数:指向内存的指针、要查找的字符以及搜索大小。memchr
执行二分搜索,不检查空终止符。对于字符串操作,strchr
可能更合适,因为它会处理以空字符结尾的字符串。
memchr 的基本用法
此示例演示了如何使用 memchr
在内存块中搜索字符。
#include <stdio.h> #include <string.h> int main() { char data[] = "Hello, World!"; char *result; char target = 'W'; // Search for 'W' in first 13 bytes result = memchr(data, target, 13); if (result != NULL) { printf("Found '%c' at position %ld\n", target, result - data); } else { printf("Character '%c' not found\n", target); } return 0; }
这里,memchr
在 data
的前 13 个字节中搜索 'W'。如果找不到,它将返回指向找到的字符的指针或 NULL。位置是通过指针算术计算的。这对于二进制数据搜索非常高效。在使用结果之前,请始终检查返回值。
在二进制数据中搜索
memchr
可以搜索二进制数据,正如这个包含整数数组的示例所示。
#include <stdio.h> #include <string.h> int main() { int numbers[] = {10, 20, 30, 40, 50}; int target = 30; void *result; // Search for value 30 in the array result = memchr(numbers, target, sizeof(numbers)); if (result != NULL) { size_t pos = ((int*)result - numbers); printf("Found %d at index %zu\n", target, pos); } else { printf("%d not found in array\n", target); } return 0; }
此示例在数组中搜索整数 30。请注意,这仅在字节表示完全匹配时才有效。在类型转换后,通过指针算术计算位置。此技术对于原始内存搜索非常有用。在使用二进制数据时,请注意字节序和对齐问题。
区分大小写的搜索
此示例演示了使用 memchr
进行区分大小写的搜索。
#include <stdio.h> #include <string.h> int main() { char text[] = "CaseSensitiveSearch"; char lower_target = 's'; char upper_target = 'S'; char *result; // Search for lowercase 's' result = memchr(text, lower_target, strlen(text)); printf("Lowercase 's' %s\n", result ? "found" : "not found"); // Search for uppercase 'S' result = memchr(text, upper_target, strlen(text)); printf("Uppercase 'S' %s\n", result ? "found" : "not found"); return 0; }
memchr
执行精确的字节匹配,因此它是区分大小写的。此示例显示了搜索 's' 和 'S' 的不同结果。对于不区分大小写的搜索,需要进行额外的处理。该函数会检查整个字符串长度。这种行为与 C 中大多数低级内存操作一致。
带有大小限制的搜索
此示例显示了如何使用 memchr
限制搜索范围。
#include <stdio.h> #include <string.h> int main() { char data[] = "SearchInPartOfTheBuffer"; char target = 'O'; size_t search_len = 10; // Only search first 10 bytes char *result = memchr(data, target, search_len); if (result) { printf("Found '%c' in first %zu bytes\n", target, search_len); } else { printf("'%c' not found in first %zu bytes\n", target, search_len); } return 0; }
在这里,memchr
只搜索缓冲区的前 10 个字节。目标 'O' 出现在字符串的后面,但不会被找到。这在处理部分缓冲区或特定内存区域时很有用。请始终确保大小参数不超过实际缓冲区大小。这可以防止读取无效的内存区域。
更安全的替代方案:memchr_s
此示例演示了 C11 中提供的更安全的 memchr_s
函数。
#define __STDC_WANT_LIB_EXT1__ 1 #include <stdio.h> #include <string.h> int main() { char buffer[20] = "SafeSearchExample"; char target = 'x'; void *result; // Safe search with bounds checking errno_t err = memchr_s(buffer, sizeof(buffer), target, sizeof(buffer), &result); if (err == 0 && result != NULL) { printf("Found '%c' at position %ld\n", target, (char*)result - buffer); } else { printf("Character '%c' not found or error occurred\n", target); } return 0; }
memchr_s
增加了边界检查,并在参数无效时返回错误。这有助于防止缓冲区溢出。该函数成功时返回零,失败时返回非零。虽然它并非普遍可用,但对于安全关键代码推荐使用。结果通过指针参数返回,而不是直接返回。
宏 __STDC_WANT_LIB_EXT1__
被定义为 1,以明确表示程序希望使用 C11 标准库中的可选扩展。如果没有这个宏,某些更安全的功能,包括 memchr_s
,可能不会由编译器提供。此功能允许开发人员选择性地启用附加功能,以提高程序的安全性和可靠性。
使用 memchr 的最佳实践
- 检查边界:确保搜索大小不超过缓冲区大小。
- 验证结果:在使用之前,务必检查返回值。
- 考虑替代方案:对于以空字符结尾的字符串,请使用
strchr
。 - 处理区分大小写:为不区分大小写的搜索实现额外的逻辑。
- 使用安全版本:在可用时,为关键代码优先使用
memchr_s
。
来源
本教程涵盖了 memchr
函数,从基本用法到高级注意事项。虽然它功能强大,但始终要小心使用内存操作,以防止程序中的安全漏洞和未定义行为。
作者
列表 C 标准库。