C语言指针与字符串详解
指针
指针是C语言中强大且重要的特性,它存储的是变量的内存地址而不是值本身。
1. 指针基础
什么是指针?
指针是一个变量,其值是另一个变量的地址。
指针声明
c
type *var-name;
示例:
c
int *ip; /* 指向整数的指针 */ double *dp; /* 指向double的指针 */ float *fp; /* 指向float的指针 */ char *ch; /* 指向字符的指针 */
指针基本操作
c
#include <stdio.h>int main() {int var = 20; /* 实际变量声明 */int *ip; /* 指针变量声明 */ip = &var; /* 在指针变量中存储var的地址 */printf("Address of var variable: %p\n", &var);printf("Address stored in ip variable: %p\n", ip);printf("Value of *ip variable: %d\n", *ip);return 0; }
2. 空指针
c
#include <stdio.h>int main() {int *ptr = NULL;printf("The value of ptr is: %p\n", ptr);/* 检查空指针 */if(ptr) /* 如果p不为null则成功 */if(!ptr) /* 如果p为null则成功 */return 0; }
3. 指针运算
指针算术运算
指针支持四种算术运算符:++
、--
、+
、-
递增指针示例:
c
#include <stdio.h>const int MAX = 3;int main() {int var[] = {10, 100, 200};int i, *ptr;/* 让指针指向数组地址 */ptr = var;for(i = 0; i < MAX; i++) {printf("Address of var[%d] = %p\n", i, ptr);printf("Value of var[%d] = %d\n", i, *ptr);/* 移动到下一个位置 */ptr++;}return 0; }
递减指针示例:
c
#include <stdio.h>const int MAX = 3;int main() {int var[] = {10, 100, 200};int i, *ptr;/* 让指针指向数组最后一个元素 */ptr = &var[MAX-1];for(i = MAX; i > 0; i--) {printf("Address of var[%d] = %p\n", i-1, ptr);printf("Value of var[%d] = %d\n", i-1, *ptr);/* 移动到前一个位置 */ptr--;}return 0; }
指针比较
c
#include <stdio.h>const int MAX = 3;int main() {int var[] = {10, 100, 200};int i, *ptr;/* 让指针指向第一个元素 */ptr = var;i = 0;while(ptr <= &var[MAX - 1]) {printf("Address of var[%d] = %p\n", i, ptr);printf("Value of var[%d] = %d\n", i, *ptr);/* 指向下一个位置 */ptr++;i++;}return 0; }
4. 指针数组
数组可以包含多个指针。
整数指针数组
c
#include <stdio.h>const int MAX = 3;int main() {int var[] = {10, 100, 200};int i, *ptr[MAX];for(i = 0; i < MAX; i++) {ptr[i] = &var[i]; /* 分配整数的地址 */}for(i = 0; i < MAX; i++) {printf("Value of var[%d] = %d\n", i, *ptr[i]);}return 0; }
字符串指针数组
c
#include <stdio.h>const int MAX = 4;int main() {char *names[] = {"Zara Ali","Hina Ali","Nuha Ali","Sara Ali"};int i = 0;for(i = 0; i < MAX; i++) {printf("Value of names[%d] = %s\n", i, names[i]);}return 0; }
5. 多重指针(指向指针的指针)
c
#include <stdio.h>int main() {int var;int *ptr;int **pptr;var = 3000;/* 获取var的地址 */ptr = &var;/* 使用&运算符获取ptr的地址 */pptr = &ptr;/* 使用pptr获取值 */printf("Value of var = %d\n", var);printf("Value available at *ptr = %d\n", *ptr);printf("Value available at **pptr = %d\n", **pptr);return 0; }
6. 指针作为函数参数
传递指针给函数
c
#include <stdio.h> #include <time.h>void getSeconds(unsigned long *par);int main() {unsigned long sec;getSeconds(&sec);/* 打印实际值 */printf("Number of seconds: %ld\n", sec);return 0; }void getSeconds(unsigned long *par) {/* 获取当前的秒数 */*par = time(NULL);return; }
传递数组给函数
c
#include <stdio.h>/* 函数声明 */ double getAverage(int *arr, int size);int main() {/* 包含5个元素的int数组 */int balance[5] = {1000, 2, 3, 17, 50};double avg;/* 传递数组指针作为参数 */avg = getAverage(balance, 5);/* 输出返回值 */printf("Average value is: %f\n", avg);return 0; }double getAverage(int *arr, int size) {int i, sum = 0;double avg;for(i = 0; i < size; ++i) {sum += arr[i];}avg = (double)sum / size;return avg; }
7. 从函数返回指针
c
#include <stdio.h> #include <time.h> #include <stdlib.h>/* 生成并返回随机数的函数 */ int *getRandom() {static int r[10]; /* 必须使用static */int i;/* 设置种子 */srand((unsigned)time(NULL));for(i = 0; i < 10; ++i) {r[i] = rand();printf("%d\n", r[i]);}return r; }/* 主函数调用上面定义的函数 */ int main() {int *p; /* 指向int的指针 */int i;p = getRandom();for(i = 0; i < 10; i++) {printf("*(p + [%d]) : %d\n", i, *(p + i));}return 0; }
字符串
字符串实际上是由空字符\0
终止的一维字符数组。
1. 字符串声明和初始化
方式1:字符数组初始化
c
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
方式2:字符串字面量
c
char greeting[] = "Hello";
内存表示:
text
索引: 0 1 2 3 4 5 值: H e l l o \0 地址:100 101 102 103 104 105
字符串输出示例
c
#include <stdio.h>int main() {char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};printf("Greeting message: %s\n", greeting);return 0; }
2. 字符串处理函数
C语言提供了丰富的字符串处理函数:
常用字符串函数
函数 | 描述 |
---|---|
strcpy(s1, s2) | 将字符串s2复制到s1 |
strcat(s1, s2) | 将字符串s2连接到s1的末尾 |
strlen(s1) | 返回字符串s1的长度 |
strcmp(s1, s2) | 比较字符串s1和s2 |
strchr(s1, ch) | 返回指向s1中字符ch首次出现的指针 |
strstr(s1, s2) | 返回指向s1中s2首次出现的指针 |
字符串函数使用示例
c
#include <stdio.h> #include <string.h>int main() {char str1[12] = "Hello";char str2[12] = "World";char str3[12];int len;/* 将str1复制到str3 */strcpy(str3, str1);printf("strcpy(str3, str1): %s\n", str3);/* 连接str1和str2 */strcat(str1, str2);printf("strcat(str1, str2): %s\n", str1);/* 连接后str1的总长度 */len = strlen(str1);printf("strlen(str1): %d\n", len);return 0; }
3. 字符串与指针
使用指针操作字符串
c
#include <stdio.h>int main() {char str[] = "Hello World";char *ptr = str;while(*ptr != '\0') {printf("%c", *ptr);ptr++;}printf("\n");return 0; }
字符串数组的指针表示
c
#include <stdio.h>int main() {char *fruits[] = {"Apple", "Banana", "Orange", "Grape"};int count = sizeof(fruits) / sizeof(fruits[0]);for(int i = 0; i < count; i++) {printf("Fruit %d: %s\n", i + 1, fruits[i]);}return 0; }
4. 字符串比较
c
#include <stdio.h> #include <string.h>int main() {char str1[] = "apple";char str2[] = "banana";char str3[] = "apple";int result;result = strcmp(str1, str2);printf("strcmp('%s', '%s') = %d\n", str1, str2, result);result = strcmp(str1, str3);printf("strcmp('%s', '%s') = %d\n", str1, str3, result);return 0; }
5. 字符串搜索函数
c
#include <stdio.h> #include <string.h>int main() {char str[] = "Hello World, welcome to C programming";char *result;/* 搜索字符 */result = strchr(str, 'W');if(result != NULL) {printf("Found 'W' at position: %ld\n", result - str);}/* 搜索子字符串 */result = strstr(str, "welcome");if(result != NULL) {printf("Found 'welcome' at position: %ld\n", result - str);}return 0; }
重要注意事项
指针注意事项:
总是初始化指针变量
检查指针是否为NULL before使用
注意指针运算的类型大小
不要返回指向局部变量的指针
字符串注意事项:
确保字符串以
\0
结尾注意数组边界,避免缓冲区溢出
使用安全的字符串函数(如
strncpy
代替strcpy
)为字符串分配足够的内存空间
掌握指针和字符串是成为优秀C程序员的关键,这些概念在内存管理、数据结构和系统编程中都有广泛应用。