index() 是一个在 C 语言中已经过时(obsolete)的函数,它存在于 POSIX 标准中,但不属于标准的 C 库(如 C89/C99/C11),它的功能是在一个字符串中查找字符第一次出现的位置。

(图片来源网络,侵删)
由于其非标准性,在现代 C 语言编程中,强烈推荐使用标准库函数 strstr() 来实现相同的功能,或者手动编写循环来查找。
index() 函数详解
函数原型
index() 函数通常在 <strings.h> 头文件中声明(注意,不是 <string.h>)。
#include <strings.h> // 注意,不是 <string.h> char *index(const char *s, int c);
参数
s: 要被搜索的字符串(以'\0'结尾的字符数组)。c: 要查找的字符,在函数内部,这个int类型的字符会被转换成char类型。
返回值
- 成功: 返回一个指向字符串
s中第一次出现字符c的位置的指针。 - 失败: 如果字符串
s中不存在字符c,则返回NULL(空指针)。
工作原理
index() 会从字符串的开头(第一个字符)开始,依次检查每个字符,直到找到匹配的字符 c 或者到达字符串的结尾('\0')。
代码示例
#include <stdio.h>
#include <strings.h> // 必须包含这个头文件
int main() {
const char *str = "Hello, world!";
char ch1 = 'w';
char ch2 = 'z';
// 查找 'w'
char *ptr1 = index(str, ch1);
if (ptr1 != NULL) {
printf("字符 '%c' 在字符串中的位置是: %ld\n", ch1, ptr1 - str);
// 输出: 字符 'w' 在字符串中的位置是: 7
} else {
printf("字符 '%c' 未找到,\n", ch1);
}
// 查找 'z'
char *ptr2 = index(str, ch2);
if (ptr2 != NULL) {
printf("字符 '%c' 在字符串中的位置是: %ld\n", ch2, ptr2 - str);
} else {
printf("字符 '%c' 未找到,\n", ch2);
// 输出: 字符 'z' 未找到。
}
return 0;
}
说明:

(图片来源网络,侵删)
ptr1 - str这种计算方式是 C 语言中常用的技巧,因为指针在内存中是连续排列的,它们相减的结果是两者之间的元素个数,也就是索引(从0开始)。index()是区分大小写的。index("Hello", 'h')会返回NULL。
为什么 index() 过时了?—— rindex() 和历史
index() 的出现有其历史原因,为了在字符串中从后向前查找字符,POSIX 标准中还提供了一个 rindex() 函数(r 代表 reverse)。
#include <strings.h> char *rindex(const char *s, int c);
rindex() 的行为与 index() 类似,但它返回的是字符 c 在字符串 s 中最后一次出现的位置的指针。
这两个函数(index 和 rindex)都源于古老的 BSD Unix 系统,后来,C 标准化委员会(ANSI/ISO)在制定 C 语言标准时,决定采用更通用的函数来处理字符串搜索,这就是 strstr() 的由来。
现代 C 语言的替代方案
使用 strstr() (推荐)
strstr() 是标准 C 库 <string.h> 中的函数,用于在一个字符串中查找另一个子字符串,我们可以巧妙地利用它来查找单个字符。

(图片来源网络,侵删)
- 函数原型:
char *strstr(const char *haystack, const char *needle);
- 查找字符: 我们需要创建一个只包含目标字符的临时字符串,然后用它作为
needle。
#include <stdio.h>
#include <string.h> // 标准头文件
int main() {
const char *str = "Hello, world!";
char ch = 'w';
// 创建一个单字符的字符串作为 "needle"
char needle[2] = {ch, '\0'};
// 使用 strstr 进行查找
char *ptr = strstr(str, needle);
if (ptr != NULL) {
printf("字符 '%c' 在字符串中的位置是: %ld\n", ch, ptr - str);
// 输出: 字符 'w' 在字符串中的位置是: 7
} else {
printf("字符 '%c' 未找到,\n", ch);
}
return 0;
}
优点:
- 标准、可移植: 任何符合标准的 C 编译器都支持。
- 功能强大: 不仅能找字符,还能找任意长度的子字符串。
手动编写循环 (最直接)
对于查找单个字符这种简单任务,手动写一个循环是最直接、最高效的方法,并且完全不需要任何特殊的头文件。
#include <stdio.h>
// 自定义的查找函数
char *my_find_char(const char *s, int c) {
if (s == NULL) {
return NULL;
}
// 遍历字符串,直到遇到空字符 '\0'
for (int i = 0; s[i] != '\0'; i++) {
if (s[i] == c) {
// 找到,返回指向该字符的指针
return (char *)&s[i]; // const char* -> char* 需要类型转换
}
}
// 遍历完没找到,返回 NULL
return NULL;
}
int main() {
const char *str = "Hello, world!";
char ch = 'w';
char *ptr = my_find_char(str, ch);
if (ptr != NULL) {
printf("字符 '%c' 在字符串中的位置是: %ld\n", ch, ptr - str);
} else {
printf("字符 '%c' 未找到,\n", ch);
}
return 0;
}
优点:
- 不依赖任何库: 代码完全自包含。
- 效率高: 没有函数调用的额外开销。
- 清晰易懂: 逻辑非常直接。
总结与对比
| 特性 | index() |
strstr() |
手动循环 |
|---|---|---|---|
| 标准性 | 非标准 (POSIX) | 标准 (C库) | 标准 (纯C) |
| 头文件 | <strings.h> |
<string.h> |
无需特殊头文件 |
| 可移植性 | 差 (Windows可能不支持) | 极佳 | 极佳 |
| 功能 | 查找单个字符 | 查找子字符串 | 查找单个字符 |
| 推荐度 | 不推荐 | 推荐 | 推荐 (尤其对于简单查找) |
最终建议:
- 永远不要在新项目中使用
index(),因为它会导致代码在不同平台(如 Windows 和 Linux)上表现出不一致的行为。 - 如果你需要查找单个字符,手动编写一个简单的循环是最好的选择,因为它高效且不依赖任何库。
- 如果你需要查找子字符串,或者希望代码风格更“库化”,那么使用
strstr()是标准且正确的做法。
