一、字符串和指针概述
1、字符串(String)
字符串是由字符(char)组成的序列,通常以空字符 '\0'(C/C++)或长度信息(如Python、Java)作为结尾。在内存中,字符串本质上是字符数组。其特点如下:
【1】存储方式:
C/C++:以字符数组形式存储,显式需要 '\0' 结尾。
高级语言(Python/Java):封装为对象,自动管理长度和内存。
【2】不可变 vs 可变:
不可变(Python、Java的String):修改字符串会创建新对象。
可变(C/C++字符数组、C++的std::string):可直接修改内容。
【3】操作复杂度:
访问字符:O(1)(随机访问)。
拼接/子串:O(n)(需复制数据)。
应用场景:
【1】文本处理
解析日志、配置文件(如JSON/XML)。
正则表达式匹配(如提取网页中的URL)。
【2】数据存储与传输
数据库中的文本字段(如SQL的VARCHAR)。
网络协议(HTTP请求/响应的报文)。
【3】加密与编码
Base64编码、哈希算法(如MD5字符串生成)。
【4】用户交互
命令行参数、输入验证(如密码复杂度检查)。
2、 指针(Pointer)
指针是存储内存地址的变量,通过地址间接访问数据。在C/C++中,指针是底层编程的核心工具;高级语言(如Java/Python)隐藏了指针,但引用(Reference)是其抽象形式。其特点为:
【1】直接内存操作
可访问任意内存位置(灵活但危险,如野指针)。
【2】高效性
避免数据复制(传递指针而非整个结构体)。
【3】多级间接访问
支持多级指针(如int**指向指针的指针)。
【4】动态内存管理
通过malloc/free(C)或new/delete(C++)手动分配内存。
应用场景:
【1】动态数据结构
链表、树、图的节点链接(如struct Node* next)。
【2】函数参数传递
修改函数外部的变量(如void swap(int* a, int* b))。
【3】硬件与系统编程
操作内存映射硬件寄存器(如嵌入式开发)。
实现系统调用(如Linux内核中的void*泛型指针)。
【4】字符串与数组的高效处理
通过指针遍历字符数组(如C中的char* str = "hello")。
【5】多态与回调
C语言中通过函数指针实现回调机制(如qsort的比较函数)。
注意事项:
【1】安全性
指针越界会导致段错误(Segmentation Fault)。
字符串操作需确保缓冲区不溢出(如strncpy替代strcpy)。
【2】内存管理
动态分配的字符串需手动释放(C/C++),否则内存泄漏。
【3】语言差异
在Python/Java中,字符串不可变且无需指针操作,但底层仍依赖类似机制。
3、字符串的创建等操作举例
用char*指向字符数组,通过指针移动遍历字符串:
char* str = "hello";
while (*str != '\0') {
printf( "%c", *str );
str++; // 指针移动
}
使用指针管理动态分配的字符串内存:
char* buffer = malloc(100 * sizeof(char));
strcpy(buffer, "Dynamic string");
free(buffer); // 手动释放
自定义strcpy、strcat等函数时依赖指针算术:
void my_strcpy(char* dest, const char* src) {
while (*dest++ = *src++); // 指针复制直到遇到'\0'
}
通过指针偏移避免复制(如返回子串的起始地址):
char* substring(const char* str, int start, int len) {
char* sub = malloc(len + 1);
strncpy(sub, str + start, len); // 指针偏移
sub[len] = '\0';
return sub;
}