一、指针和字符串
1.1 字符串和字符数组的关系
在 C 语言中,字符串是由字符组成的字符数组,以空字符(‘\0’,ASCII 值为 0)作为结尾。
下面是一个示例代码,演示了字符串和字符数组的关系:
#include <stdio.h> #include <string.h> int main() { // 直接初始化字符数组 char str1[] = "Hello, World!"; // 声明字符数组并赋值 char str2[15]; str2[0] = 'H'; str2[1] = 'e'; str2[2] = 'l'; str2[3] = 'l'; str2[4] = 'o'; str2[5] = '\0'; // 字符串的结尾需要加上空字符 printf("str1: %s\n", str1); printf("str2: %s\n", str2); // 通过字符数组逐个字符访问和修改字符串 str1[7] = 'w'; printf("Modified str1: %s\n", str1); // 使用字符数组进行字符串拼接 char str3[30] = "Welcome "; char name[] = "Alice"; strcat(str3, name); printf("str3: %s\n", str3); return 0; }
输出结果如下:
1.2 字符串常量和字符指针的使用
在 C 语言中,字符串常量是由连续的字符组成的字符数组,以空字符 '\0'
结束。字符串常量使用双引号 "
括起来。例如:
char str[] = "Hello, World!"; // 字符数组,其内容为字符串常量
字符串常量在内存中被存储为只读数据,在大多数情况下,不能对其进行修改。因此,通常将字符串常量声明为字符指针(const char*
类型),来指向字符串常量的首地址。例如:
const char* str = "Hello, World!"; // 字符指针,指向字符串常量
以下是一个关于字符串常量和字符指针的使用示例代码:
#include <stdio.h> int main() { // 声明字符串常量 char str1[] = "Hello, World!"; // 字符数组 const char* str2 = "Hello, World!"; // 字符指针 printf("str1: %s\n", str1); printf("str2: %s\n", str2); // 使用字符指针访问字符串 char* ptr = str1; // 字符指针指向字符数组 while (*ptr != '\0') { printf("%c", *ptr); ptr++; } printf("\n"); return 0; }
输出结果如下:
1.3 字符串函数库的指针参数
C 语言提供了一组字符串函数库(如 <string.h>)来操作字符串。 这些字符串函数通常使用指针参数来接收和处理字符串数据。例如strlen、strcpy、strcat、strcmp 等。
1.3.1
strlen
函数
strlen
函数接受一个指向字符串的指针,并返回该字符串的长度,即字符的个数。
示例代码:
#include <stdio.h> #include <string.h> int main() { char str[] = "Hello,WeTab!"; size_t len = strlen(str); printf("Length of the string: %zu\n", len); return 0; }
输出结果如下:
注意:strlen
函数只计算字符串中的字符数目,不包括字符串末尾的空字符 \0
。这是因为在 C 语言中,字符串以空字符作为结束标志。
1.3.2
strcpy 函数
strcpy 函数接受两个参数,一个目标字符串和一个源字符串的指针。它将源字符串中的内容复制到目标字符串中,并返回目标字符串的指针。
示例代码:
#include <stdio.h> #include <string.h> int main() { char source[] = "Hello, WeTab!"; char destination[50]; strcpy(destination, source); printf("Copied string: %s\n", destination); return 0; }
输出结果如下:
注意:strcpy
函数会将源字符串中的内容复制到目标字符串中,包括末尾的空字符 \0
。因此,在目标字符串中需要有足够的空间来存储源字符串的内容。建议在使用 strcpy
函数时,确保目标字符串足够大,以避免发生缓冲区溢出的问题。
1.3.3
strcat 函数
strcat 函数接受两个参数,一个目标字符串和一个源字符串的指针。它将源字符串中的内容追加到目标字符串的末尾,并返回目标字符串的指针。
示例代码:
#include <stdio.h> #include <string.h> int main() { char destination[50] = "Hello,"; char source[] = " WeTab!"; strcat(destination, source); printf("Concatenated string: %s\n", destination); return 0; }
输出结果如下:
注意:strcat
函数会将源字符串中的内容追加到目标字符串的末尾,并在末尾加上空字符 \0
。因此,在使用 strcat
函数之前,目标字符串必须以空字符结尾,并且有足够的空间来存储源字符串的内容和终止空字符。此外,类似 strcpy
函数,使用 strcat
函数时也应注意目标字符串的长度和避免发生缓冲区溢出的问题。
1.3.4
strcmp 函数
strcmp 函数接受两个参数,两个字符串的指针。它将两个字符串进行比较,并返回一个整数:
如果 str1 按照字典序小于 str2,返回负数;
如果 str1 等于 str2,返回 0;
如果 str1 按照字典序大于 str2,返回正数。
示例代码:
#include <stdio.h> #include <string.h> int main() { char str1[] = "hello"; char str2[] = "world"; char str3[] = "hello"; int result1 = strcmp(str1, str2); int result2 = strcmp(str1, str3); printf("strcmp(str1, str2) 返回值: %d\n", result1); printf("strcmp(str1, str3) 返回值: %d\n", result2); return 0; }
输出结果如下:
二、指针的高级应用
2.1 函数指针的定义和使用
函数指针是指向函数的指针,可以将其视为指向包含函数代码的内存位置的指针。
函数指针的类型定义为:返回类型 (*指针变量名)(参数列表)。
可以通过名称或指针来调用函数,函数指针可以用来动态调用函数。
示例代码:
#include <stdio.h> // 声明一个函数指针类型 typedef int (*Operation)(int, int); // 定义加法函数 int add(int a, int b) { return a + b; } // 定义减法函数 int subtract(int a, int b) { return a - b; } int main() { // 定义函数指针变量 Operation op; // 把函数赋值给函数指针变量 op = add; // 通过指针变量调用函数 int result = op(5, 3); printf("加法的结果: %d\n", result); // 修改指针变量的值,指向减法函数 op = subtract; // 通过指针变量调用函数 result = op(5, 3); printf("减法的结果: %d\n", result); return 0; }
输出结果如下:
2.2 回调函数和函数指针数组的应用
2.2.1 回调函数
回调函数是指当我们调用一个函数时,把另一个函数的指针作为一个参数传递给它,在这个函数完成后再调用这个指针所指向的函数,这就是回调函数。
示例代码:
#include <stdio.h> // 回调函数类型 typedef void (*Callback)(int); // 函数指针变量数组类型 typedef Callback CallbackArray[3]; // 回调函数实现 void my_callback(int number) { printf("回调函数被调用,参数为:%d\n", number); } // 调用函数 void call_function(Callback callback_func) { printf("调用函数执行...\n"); callback_func(123); printf("调用函数结束。\n"); } int main() { // 使用回调函数 printf("使用回调函数:\n"); call_function(my_callback); // 使用函数指针数组 printf("使用函数指针数组:\n"); CallbackArray callbacks = { my_callback, my_callback, my_callback }; callbacks[0](1); callbacks[1](2); callbacks[2](3); return 0; }
输出结果如下:
2.2.2 函数指针数组
函数指针数组是指向函数指针的指针数组,可以用于存储多个函数指针。
函数指针数组的声明方式如下:
ReturnType (*FunctionName[])(ParameterTypes) = {Function1, Function2, ..., FunctionN};
其中,ReturnType
表示函数的返回类型,FunctionName
表示函数指针数组的名称,ParameterTypes
表示函数的参数类型,Function1
到FunctionN
表示要存储在数组中的函数指针。
示例代码:
#include <stdio.h> // 函数原型 void Function1(); void Function2(); void Function3(); int main() { // 定义函数指针数组 void (*functionPointers[])(void) = {Function1, Function2, Function3}; // 调用函数指针数组中的函数 functionPointers[0](); // 调用Function1 functionPointers[1](); // 调用Function2 functionPointers[2](); // 调用Function3 return 0; } void Function1() { printf("This is Function1.\n"); } void Function2() { printf("This is Function2.\n"); } void Function3() { printf("This is Function3.\n"); }
输出结果如下:
函数指针数组在C语言中经常用于实现回调机制和多态。通过存储不同函数的指针,我们可以在运行时动态地选择执行不同的函数,从而实现程序的可扩展性和灵活性。