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 标准库。