C指针总结复习(结合deepseek)

一、指针数组 (Array of Pointers)

一维数组

cpp 复制代码
int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	int (*ptr)[5] = &arr;
	int* p = arr;
	// 访问元素方式
	printf("%d\n", p[2]); //输出3
	printf("%d\n", (*ptr)[2]);  // 输出3
	printf("%d\n", ptr[0][2]);  // 同上,输出3
	/*
	p 是一个 int* 类型的指针,指向数组的第一个元素
    p[2] 等价于 *(p + 2),通过指针算术访问第三个元素
	这是最常用的数组访问方式

	ptr 是一个指向整个数组的指针,类型是 int(*)[5]
	*ptr 解引用得到数组本身(arr)
	(*ptr)[2] 等价于 arr[2]

	ptr[0] 等价于 *(ptr + 0),即解引用得到数组本身
	ptr[0][2] 相当于先取数组,再取数组的第三个元素
	这种写法暗示 ptr 可以看作是指向二维数组的行指针
	*/
	return 0;
}

二维数组

cpp 复制代码
int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

// 数组指针指向包含4个int的数组
int (*ptr)[4] = matrix;

// 访问元素
printf("%d\n", ptr[1][2]);  // 输出7
printf("%d\n", (*(ptr + 1))[2]);  // 同上,输出7

sizeof 操作符与指针、数组的关系 (64位下)

cpp 复制代码
#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *ptr = arr;
    
    printf("sizeof(arr): %zu\n", sizeof(arr));      // 数组总大小
    printf("sizeof(ptr): %zu\n", sizeof(ptr));    // 指针大小
    printf("sizeof(&arr): %zu\n", sizeof(&arr));   // 指针大小
    printf("sizeof(*ptr): %zu\n", sizeof(*ptr));   // int大小
    printf("sizeof(arr[0]): %zu\n", sizeof(arr[0])); // 单个元素大小
    
    return 0;
}
cpp 复制代码
sizeof(arr): 20      // 5个int × 4字节 = 20字节
sizeof(ptr): 8       // 指针在64位系统占8字节
sizeof(&arr): 8      // 数组指针也是指针
sizeof(*ptr): 4      // int类型大小
sizeof(arr[0]): 4    // int类型大小

二、函数指针

返回值类型 (*指针变量名)(参数类型列表);

cpp 复制代码
int add(int a, int b) 
{
    return a + b;
}
int main()
{
	//返回值类型 (*指针变量名)(参数类型列表);
	int (*funcPtr)(int, int);  // 定义一个指向函数的指针,该函数接受两个int参数并返回int
    funcPtr = add;  // 或者 = &add
	int result = funcPtr(3, 4);  // 等同于 add(3, 4)
	// 或者
	result = (*funcPtr)(3, 4);  // 显式解引用
	printf("%d", result);//7
	return 0;
}

函数指针数组

cpp 复制代码
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }

int main() {
    int (*operations[3])(int, int) = {add, sub, mul};
    
    for (int i = 0; i < 3; i++) {
        printf("%d\n", operations[i](10, 5));
    }
    // 输出:
    // 15 (10 + 5)
    // 5  (10 - 5)
    // 50 (10 * 5)
    return 0;
}

高级用法

cpp 复制代码
typedef int (*MathFunc)(int, int);//将int(*)(int,int) 简化为 MathFunc类型

int add(int a, int b) { return a + b; }

int main() 
{
    MathFunc func = add;//此时func就是int(*)(int,int)型指针
    printf("%d\n", func(2, 3));  // 输出5
    return 0;
}

回调函数

cpp 复制代码
void processArray(int *arr, int size, int (*callback)(int)) {
    for (int i = 0; i < size; i++) {
        arr[i] = callback(arr[i]);
    }
}

int square(int x) { return x * x; }
int increment(int x) { return x + 1; }

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    
    processArray(arr, 5, square);
    // arr现在是 [1, 4, 9, 16, 25]
    
    processArray(arr, 5, increment);
    // arr现在是 [2, 5, 10, 17, 26]
    
    return 0;
}

C++中的函数指针

C++中还可以使用函数对象和lambda表达式,但函数指针仍然有效:

cpp 复制代码
#include <iostream>
using namespace std;

int add(int a, int b) { return a + b; }

int main() {
    int (*func)(int, int) = add;
    cout << func(3, 4) << endl;  // 输出7
    
    // 使用auto更简洁
    auto func2 = add;
    cout << func2(5, 6) << endl;  // 输出11
    
    return 0;
}
注意事项
  1. 函数指针的类型必须与所指向的函数完全匹配(返回值类型和参数类型)

  2. 不要对函数指针进行不安全的类型转换

  3. 空函数指针(nullptr)需要先检查再调用

  4. 成员函数指针与普通函数指针不同(在C++中)

三、const 和 指针

const 关键字与指针结合使用时,会产生多种不同的含义,这取决于 const 修饰的是指针本身还是指针所指向的数据。理解这些区别对于编写安全、可靠的C/C++代码至关重要。

1. 指向常量数据的指针 (Pointer to constant data)

cpp 复制代码
const int *ptr;  // 或 int const *ptr;
cpp 复制代码
const int x = 10;
const int *ptr = &x;
// *ptr = 20;  // 错误:不能修改常量数据
int y = 30;
ptr = &y;      // 合法:可以改变指针指向
  • 特点:指针可以修改(指向不同的地址),但不能通过指针修改所指向的数据

  • 用途:保护数据不被意外修改

2. 常量指针 (Constant pointer)

cpp 复制代码
int *const ptr;
cpp 复制代码
int x = 10;
int *const ptr = &x;
*ptr = 20;     // 合法:可以修改指向的数据
// ptr = &y;   // 错误:不能改变指针本身
  • 特点:指针本身是常量(不能指向其他地址),但可以通过指针修改所指向的数据

  • 用途:确保指针始终指向特定内存位置

  1. 指向常量数据的常量指针 (Constant pointer to constant data)
cpp 复制代码
const int *const ptr;
cpp 复制代码
const int x = 10;
const int *const ptr = &x;
// *ptr = 20;  // 错误:不能修改数据
// ptr = &y;   // 错误:不能修改指针
  • 特点:指针不能修改,也不能通过指针修改数据

  • 用途:完全保护数据和指针

四、库函数的实现

1、memcpy 实现

memcpy 用于从源内存地址复制n个字节到目标内存地址,不处理内存重叠情况。

cpp 复制代码
void* my_memcpy(void* dest, const void* src, size_t n) {
    if (dest == NULL || src == NULL || n == 0) {
        return dest;
    }
    
    char* d = (char*)dest;
    const char* s = (const char*)src;
    
    // 逐字节复制
    for (size_t i = 0; i < n; i++) {
        d[i] = s[i];
    }
    
    return dest;
}

特点

  • 不检查内存重叠

  • 简单高效的逐字节复制

  • 返回目标指针以便链式调用

2. memmove 实现

memmove 也用于内存复制,但会正确处理源和目标内存重叠的情况。

cpp 复制代码
void* my_memmove(void* dest, const void* src, size_t n) {
    if (dest == NULL || src == NULL || n == 0) {
        return dest;
    }
    
    char* d = (char*)dest;
    const char* s = (const char*)src;
    
    // 判断是否有重叠
    if (d > s && d < s + n) {
        // 从后向前复制以避免覆盖
        for (size_t i = n; i > 0; i--) {
            d[i-1] = s[i-1];
        }
    } else {
        // 无重叠或源在前,正常复制
        for (size_t i = 0; i < n; i++) {
            d[i] = s[i];
        }
    }
    
    return dest;
}

特点

  • 检测内存重叠情况

  • 重叠时从后向前复制

  • 非重叠时从前向后复制

  • 同样返回目标指针

3. strstr 实现

cpp 复制代码
char* my_strstr(const char* haystack, const char* needle) {
    if (haystack == NULL || needle == NULL || *needle == '\0') {
        return (char*)haystack;
    }
    
    for (; *haystack != '\0'; haystack++) {
        const char* h = haystack;
        const char* n = needle;
        
        while (*h != '\0' && *n != '\0' && *h == *n) {
            h++;
            n++;
        }
        
        if (*n == '\0') {
            return (char*)haystack;
        }
    }
    
    return NULL;
}

特点

  • 处理空指针和空子串的特殊情况

  • 外层循环遍历主字符串

  • 内层循环比较子串

  • 返回首次匹配的位置指针或NULL

相关推荐
双叶8369 天前
(C语言)Map数组的实现(数据结构)(链表)(指针)
c语言·数据结构·c++·算法·链表·哈希算法
XiaoCCCcCCccCcccC10 天前
C语言数组介绍 -- 一维数组和二维数组的创建、初始化、下标、遍历、存储,C99 变长数组
c语言·数据结构·算法
岁忧10 天前
第十六届蓝桥杯C/C++程序设计研究生组国赛 国二
c语言·c++·算法·蓝桥杯
一ge科研小菜鸡10 天前
编程语言的设计之道:从底层控制到表达自由
java·c语言·c++·python
天若有情67310 天前
技术逐梦之旅:从C语言到Vue的成长之路
c语言·开发语言·vue.js
Jess0710 天前
队的简单介绍
c语言
攻城狮7号10 天前
【AI时代速通QT】第二节:Qt SDK 的目录介绍和第一个Qt Creator项目
c语言·c++·qt·跨平台
jz_ddk10 天前
[学习] C语言<string.h>中字符串函数全解析
c语言·开发语言·学习