手写500行源码带你彻底吃透C指针底层核心重难点-知识点全解(血泪教训+高频面试题)

1 你是否渴望在短时间内彻底攻克 C 语言指针这一重难点?

本人耗时 5 天,手敲 600 行代码,精心整理了全部 C 语言数组与指针的常见考点及面试重难点。通过多个精心设计的实验,涵盖数组元素访问、多维数组转置、动态内存分配、字符串操作、函数指针、链表操作、排序算法、结构体嵌套等内容,深度剖析指针在 C 语言中的应用

每个实验都包含:

  • 1底层原理剖析:揭秘指针与数组的本质关联

  • 2调试技巧:教你在GDB中追踪内存泄漏

  • 3性能优化:掌握位运算在嵌入式开发中的实战应用

  • 4面试高频考点:覆盖腾讯T3/4、字节跳动SP级别的真题解析

2 上代码!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

// 指针访问数组中的元素
void arr1_ptr()
{
    int arr[] = {1, 2, 4, 5, 6, 56, 67, 8, 9};
    int *ptr = arr;
    int len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < len; i++)
    {
        printf("指针访问:%d,数组访问:%d\n ", *(ptr + i), arr[i]);
    }
}

// 转置操作
// #self 数组没办法获取数组大小 :sizeof(arr)这个会失效!!!
void zhuanzhi(int arr[3][3])
{
    for (int i = 0; i < 3; i++)
    {
        for (int j = i + 1; j < 3; j++)
        {
            int temp = arr[i][j];
            arr[i][j] = arr[j][i];
            arr[j][i] = temp;
        }
    }
}

static void dy_alloc_mem()
{
    int *arr1 = (int *)malloc(1000000 * sizeof(int));
    if (arr1 == NULL)
    {
        printf("内存分配失败!\n");
        return;
    }
    for (int i = 0; i < 1000000; i++)
    {
        *(arr1 + i) = i;
    }
    // 时间戳1
    clock_t start, end;
    start = clock();
    int i;
    for (i = 0; i < 100; i++)
    {
        printf("%d \n", *(arr1 + i));
    }
    end = clock();
    double t = (double)(end - start);
    printf("打印这些%d用了%10f毫秒\n", i, t);
    //
    // 时间戳2
}

void string_reverse(char *str, int len)
{

    char *start = str;
    char *end = start + len - 1;
    while (start < end)
    {
        char temp = *start;
        *start = *end;
        *end = temp;
        start++;
        end--;
    }
}

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

int substract(int a, int b)
{
    return a - b;
}

struct Person
{

    char name[10];
    int age;
};

struct Node
{
    int data;
    struct Node *next;
};

struct Node *insert_atFirst(struct Node *head, int data)
{
    // self
    // vip!!!
    //  在末尾插入!
    struct Node *n_node = (struct Node *)malloc(sizeof(struct Node));
    n_node->data = data;
    n_node->next = head;
    return n_node;
}

void print_List(struct Node *node)
{
    struct Node *l = node;
    while (l != NULL)
    {
        printf("这是打印的节点:!!! %d \n", l->data);
        l = l->next;
    }
    return;
}

void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

int cnt11 = 0;

int partition(int arr[], int low, int high)
{
    int pi = arr[high];
    int i = low - 1;
    for (int j = low; j <= high - 1; j++)
    {
        if (arr[j] <= pi)
        {
            i++;
            swap(&arr[i], &arr[j]);
        }
    }
    swap(&arr[i + 1], &arr[high]);
    printf("\n\n---现在是partition%d次调用\n,pi是%d\n", cnt11++, pi);

    for (int i = 0; i < high; i++)
    {
        printf(" %d-", arr[i]);
    }
    printf("---现在是partition%d次调用\n\n", cnt11++);

    return i + 1;
}

void quick_Sort(int arr[], int low, int high)
{
    if (low < high)
    {
        int pi = partition(arr, low, high);
        quick_Sort(arr, low, pi - 1);
        quick_Sort(arr, pi + 1, high);
    }
}

struct Address{
    char street[50];
    int house_number;
};

struct Person_16{
    char name[20];
    struct Address address;
};

void Print_address(struct Person_16* p){
    printf("%s \n",p->name);
    printf("%s \n",p->address.street);
    printf("%d \n",p->address.house_number);
}

//#self vip !!!!
//不自己写 根本就不知道有这么多不懂的内容!
void connect_char(char* a,char* b){
    char* p1 = a + strlen(a);
    printf("这是实验18里面的callback,a的长度是:%d ,b的长度是:%d\n",strlen(a),strlen(b));

    // for(int i=0;i<strlen(b);i++){
    //     a[i] = b[i];

    // }
    while(*b!='\0'){
        *p1 = *b;
        p1++;b++;
    }
    *p1 = '\0';
}

#define maxL 100

struct stack{
    int data[maxL] ;
    int top ;
};

void initStack(struct stack* s ){
    s->top=-1;
}

int isEmpty(struct stack* s ){
    if(s->top==-1){
        return 1;
    }
    else{
        return -100;
    }
}

int isFull(struct stack* s ){
    if(s->top==maxL){
        return 1;
    }
    else{
        return 0;
    }
}

void pushStack(struct stack* s ,int data ){
    //判断栈是不是满了?
    if(s->top==maxL){
        return  ;
    }
    else{
        s->data[++(s->top)] = data;
    }
}

int  popStack(struct stack* s ){
    //判断是不是空?空了就返回-1
    if(isEmpty(s)){
        return -1;
    }
    else{
        int res  = s->data[s->top--];
    }
}

int peekTop(struct stack* s ){
    return s->data[s->top];
}

int main()
{

    // 访问数组元素
    // arr1_ptr();
    // printf("1 访问数组元素结束!\n");

    // // 多维数组的内存布局
    // // 把一个二维数组转置操作一下
    // // #self 数组没办法获取数组大小 :sizeof(arr)这个会失效!!!
    // int arr[3][3] = {
    //     {1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    // zhuanzhi(arr);
    // for (int i = 0; i < 3; i++)
    // {
    //     for (int j = 0; j < 3; j++)
    //     {
    //         printf("%d ", arr[i][j]);
    //     }
    //     printf("\n");
    // }
    // printf("\n\n实验转置操作\n");

    // // 动态分配内存打印
    // printf("第3实验开始!\n");
    // dy_alloc_mem();
    // printf("第3实验结束!\n");

    // printf("\n\n第四个实验开始\n\n");
    // char charS[100] = {'0', '1', '2', '3', '4', '5', '\0'};
    // int char_len = strlen(charS);
    // printf("这个字符数组的长度:%d \n", char_len);
    // printf("但是强行从0-100打印就是:\n");
    // for (int i = 0; i < 5; i++)
    // {
    //     printf("%c \n", charS[i]);
    // }

    // string_reverse(charS, char_len);
    // for (int i = 0; i < char_len; i++)
    // {
    //     printf("%c \n", charS[i]);
    // }
    // printf("第4个实验结束\n\n");

    // // 第5个实验:函数指针
    // // 手动实现一个计算器
    // printf("\n第5个实验开始\n\n");
    // int a = 100, b = 50;
    // int (*func_ptr)(int a, int b);

    // printf("告诉我你要的操作:\n");
    // char op;
    // scanf("%c", &op);
    // switch (op)
    // {
    // case '+':
    //     func_ptr = add;
    //     {
    //         int res = func_ptr(a, b);
    //         printf("%d\n", res);
    //         break;
    //     }
    // case '-':
    //     func_ptr = substract;
    //     {
    //         int res = func_ptr(a, b);
    //         printf("%d\n", res);
    //         break;
    //     }
    // }
    // printf("\n第5个实验结束\n\n");

    // printf("\n第六个实验,二维数组动态分配\n");

    // int m =3,n =4 ;
    // int **arr_6 =(int**)malloc(m*sizeof(int*));
    // for(int i= 0;i<m;i++){
    //     arr_6[i] = (int*)malloc(n*sizeof(int));
    // }
    // for(int i =0;i<m;i++){
    //     for(int j =0;j<n;j++){
    //         arr_6[i][j] = i*n+j;
    //         printf("\n%d = %d 行 %d列",arr_6[i][j],i,j);
    //     }
    //     printf("\n");
    // }
    // printf("\n第六个实验,二维数组动态分配\n");

    printf("实验7 指针数组用法\n");
    char *string[] = {"jibamao", "abc", "123", "why", "你是神秘嘉宾", "\0"};
    int len7 = sizeof(string) / sizeof(string[0]);
    for (int i = 0; i < len7; i++)
    {
        printf("%s\n", string[i]);
    }
    char string7[] = "123123";

    printf("%d\n", sizeof(string7));
    for (int i = 0; i < sizeof(string7); i++)
    {
        printf("%c", string7[i]);
    }
    // #self vip
    // 特别重要 字符串数组和字符指针数组

    // 结构体指针8 实验8 结构体修改结构体内值
    //
    struct Person person = {"xiaomin", 18};
    printf("\n%s-%d\n", person.name, person.age);

    struct Person *p = &person;
    strcpy(p->name, "jibamao");
    // p->name = "jibamao";
    printf("改过之后:%s\n", p->name);
    // #self vip!
    // 结构体指针的作用

    // #self
    // 实验9 链表节点的插入
    printf("\n\n实验9 链表的插入\n");
    struct Node *head_node = NULL;
    // struct Node node = {123,NULL};
    head_node = insert_atFirst(head_node, 123);
    printf("\n第一个节点:%d\n  ", head_node->data);

    head_node = insert_atFirst(head_node, 4);
    printf("\n第二个节点 : %d\n", head_node->data);
    print_List(head_node);

    // #self  vip!!!
    // 实验10 冒泡排序优化
    printf("实验10 冒泡排序优化!\n");

    // 11 快排法
    // #self vip!!!
    printf("\n\n实验11 快速排序!!开始!!!\n");
    int arr11[] = {4, 5, 6, 7, 15, 234, 46, 698, 238, 258, 45, 2, 36, 26, 123, 77, 5, 48, 45, 2, 5, 325, 32, 1, 6};
    int len = sizeof(arr11) / sizeof(arr11[0]);
    quick_Sort(arr11, 0, len - 1);
    for (int i = 0; i < len; i++)
    {
        printf("快排打印的结果是");
        printf("%d\n", arr11[i]);
    }
    printf("\n\n实验11 快排结束!!!\n");

    // 13实验 文件读写操作
    //

    // 14整数阶乘

    // 15指针数组与二维数组区别:
    // #self vip
    printf("\n\n实验15开始 \n\n");
    char *str15[] = {"ab", "123", "efg", "jkl"};
    char str15new[3][10] = {"baname", "apple", "milk"};
    int len1 = sizeof(strlen(str15))/sizeof(str15[0]);
    for (int i = 0; i <len1; i++)
    {
        printf("%s \n", str15[i]);
    }
    printf("\n\n");
    for (int i = 0; i < strlen(str15new); i++)
    {
        printf("%s \n", str15new[i]);
    }

    //实验16 结构体嵌套  
    printf("\n\n实验16开始 \n\n");

    struct Person_16 p16 = {"xiaom",{"123abc",100}};
    Print_address(&p16);
    printf("\n\n实验16结束 \n\n");


    //实验17 位运算实现假发


    //shyan 18 指针实现字符串拼接
    //告诉两个指针的地址,直接把连个地址相加即可
    printf("\n\n实验18开始 ---------\n\n");

    char char1 []= {'1','2','3','4','5','a','\0'};
    char char2 []= {'b','9','\0'};
    connect_char(char1,char2);
    int len18 = strlen(char1);
    printf("\n18实验的长度是:%d \n\n",len18);

    for(int i =0;i<len18;i++){
        printf("%c \n",char1[i]);
    }
    printf("\n\n实验18结束 ---------------\n\n");

    //实验19 
    //later
    //检测是否链表有环形结构

    //实验20
    //自己实现一个栈结构
    //#self vip!!!
    //栈要实现哪些功能?
    //1 初始化 2入栈  3出栈   4查看栈顶元素  5空了?   6满了?
    struct stack s;
    initStack(&s);

    printf("初始了,是不是空?%d\n",isEmpty(&s));
    pushStack(&s,1);
    printf("插入了1,是不是空?\n",isEmpty(&s));
    pushStack(&s,2);
    pushStack(&s,3);
    printf("栈顶是:%d\n",peekTop(&s));

    pushStack(&s,4);
    printf("栈顶是:%d\n",peekTop(&s));
    popStack(&s);
    printf("栈顶是:%d\n",peekTop(&s));
    printf("栈顶是:%d\n",peekTop(&s));





    return 0;
}

3  写给正在攀登技术高峰的你

“当初我学void (*signal(int sig, void (*handler)(int)))(int);时,整整3天没看懂。后来在深圳凌晨3点的出租屋里,当我突然顿悟函数指针声明的语法时,那种颅内高潮般的快感,至今难忘。”

特别提示:文末提供完整源码包(含调试注释),前100名私信者可获取《C语言指针进阶手册》PDF版。技术的道路上,我们永远在互相成就!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值