大数跨境

绝了!这17个C指针玩法,让无数程序员连夜收藏

绝了!这17个C指针玩法,让无数程序员连夜收藏 芯片之家
2025-06-23
1

哈喽,大家好,我是小康。

今天,咱们来聊聊 C 语言里最让人又爱又恨的东西——指针!

别一听到指针就头疼,今天我保证让你看完之后直呼"卧槽,原来还能这么玩!"


玩法一:指针当计算器用

你知道吗?指针其实是个天生的数学家!看这个:

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int *p = arr;
    
    printf("原来的值:%d\n", *p);        // 输出:10
    printf("往后跳一步:%d\n", *(p+1));  // 输出:20
    printf("往后跳三步:%d\n", *(p+3));  // 输出:40
    
    return 0;
}

看到没?指针加个数字就能跳到别的位置!就像在数组里蹦迪一样,想跳哪就跳哪。

玩法二:指针的"换身术"

这个绝对震撼你三观!两个变量的值,用指针一秒钟就能互换:

#include <stdio.h>

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

int main() {
    int x = 100, y = 200;
    
    printf("交换前:x=%d, y=%d\n", x, y);  // 输出:x=100, y=200
    swap(&x, &y);
    printf("交换后:x=%d, y=%d\n", x, y);  // 输出:x=200, y=100
    
    return0;
}

是不是感觉像变魔术?两个数字眨眼间就换了位置!

玩法三:指针数组——批量管理大法

想象一下,你有一堆字符串要管理,用指针数组简直不要太爽:

#include <stdio.h>

int main() {
    constchar *names[] = {"小明", "小红", "小刚", "小美"};
    
    printf("班级名单:\n");
    for(int i = 0; i < 4; i++) {
        printf("%d. %s\n", i+1, names[i]);
    }
    
    // 输出:
    // 1. 小明
    // 2. 小红  
    // 3. 小刚
    // 4. 小美
    
    return0;
}

一个数组装下所有字符串,想用哪个直接拿,简直是管理神器!

玩法四:函数指针——让函数也能当变量

这个玩法绝对让你大开眼界!函数居然也能用指针指着:

#include <stdio.h>

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

int multiply(int a, int b) {
    return a * b;
}

int main() {
    int (*operation)(int, int);  // 声明一个函数指针
    
    operation = add;             // 指向加法函数
    printf("5 + 3 = %d\n", operation(5, 3));  // 输出:8
    
    operation = multiply;        // 指向乘法函数  
    printf("5 * 3 = %d\n", operation(5, 3));  // 输出:15
    
    return0;
}

看到没?同一个指针,一会儿做加法,一会儿做乘法,简直是变脸高手!

玩法五:动态内存——想要多少给多少

这个真的太实用了!想要多大内存,现场申请:

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

int main() {
    int n;
    printf("你想要几个整数的空间?");
    scanf_s("%d", &n);

    int* arr = (int*)malloc(n * sizeof(int));  // 动态申请内存

    // 填充数据
    for (int i = 0; i < n; i++) {
        arr[i] = (i + 1) * 10;
    }

    // 输出结果
    printf("动态数组的内容:");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr);  // 记得释放内存!
    return0;
}

想要3个就给3个,想要100个就给100个,完全按需分配!

玩法六:指针的指针——套娃游戏

这个有点绕,但是很有趣!指针也能被别的指针指着:

#include <stdio.h>

int main() {
    int num = 42;
    int *p1 = &num;      // p1指向num
    int **p2 = &p1;      // p2指向p1
    
    printf("直接访问:%d\n", num);        // 输出:42
    printf("一级指针:%d\n", *p1);        // 输出:42
    printf("二级指针:%d\n", **p2);       // 输出:42
    
    // 通过二级指针修改值
    **p2 = 100;
    printf("修改后的值:%d\n", num);      // 输出:100
    
    return0;
}

就像俄罗斯套娃,一层套一层,但最后都能找到那个宝贝!

玩法七:指针遍历字符串——速度飞快

用指针遍历字符串,效率杠杠的:

#include <stdio.h>

int main() {
    char str[] = "Hello World!";
    char *p = str;
    
    printf("逐个字符输出:\n");
    while(*p != '\0') {
        printf("%c ", *p);
        p++;  // 指针往前走
    }
    printf("\n");
    
    // 输出:H e l l o   W o r l d !
    
    return0;
}

指针一步步往前走,把每个字符都拿到手,简单粗暴!

玩法八:指针数组vs数组指针——双胞胎的区别

这两个长得很像,但作用完全不同:

#include <stdio.h>

int main() {
    // 指针数组:是个数组,里面装的都是指针
    char *arr1[] = {"苹果", "香蕉", "橙子"};
    
    // 数组指针:是个指针,指向一个数组
    int nums[] = {1, 2, 3, 4, 5};
    int (*arr2)[5] = &nums;
    
    printf("指针数组的内容:\n");
    for(int i = 0; i < 3; i++) {
        printf("%s ", arr1[i]);
    }
    printf("\n");
    
    printf("数组指针指向的数组:\n");
    for(int i = 0; i < 5; i++) {
        printf("%d ", (*arr2)[i]);
    }
    printf("\n");
    
    return0;
}

记住:指针数组是装指针的盒子,数组指针是指向盒子的手!

玩法九:指针运算的神奇魔法

指针还能做减法运算,算出两个位置的距离:

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int *start = &arr[1];  // 指向20
    int *end = &arr[4];    // 指向50
    
    printf("两个指针的距离:%ld个位置\n", end - start);  // 输出:3
    printf("从%d到%d,中间隔了%ld个数\n", *start, *end, end - start);
    
    return 0;
}

指针一减,立马知道隔了多少个位置,简直是内置的测距仪!

玩法十:void指针——万能胶水

这个指针太牛了,什么类型都能指:

#include <stdio.h>

int main() {
    int num = 100;
    float pi = 3.14;
    char ch = 'A';
    
    void *magic_ptr;  // 万能指针
    
    magic_ptr = &num;
    printf("指向整数:%d\n", *(int*)magic_ptr);      // 输出:100
    
    magic_ptr = &pi;
    printf("指向小数:%.2f\n", *(float*)magic_ptr);  // 输出:3.14
    
    magic_ptr = &ch;
    printf("指向字符:%c\n", *(char*)magic_ptr);     // 输出:A
    
    return0;
}

一个指针走天下,想指啥就指啥,就是用的时候要记得转换类型!

玩法十一:指针与结构体的完美搭配

结构体遇上指针,简直是天作之合:

#include <stdio.h>

struct Student {
    char name[20];
    int age;
    float score;
};

int main() {
    struct Student stu = {"小明", 18, 95.5};
    struct Student *p = &stu;
    
    // 两种访问方式,效果一样
    printf("方式1 - (*p).name: %s\n", (*p).name);    // 输出:小明
    printf("方式2 - p->name: %s\n", p->name);         // 输出:小明
    
    // 修改数据也超简单
    p->age = 19;
    p->score = 98.0;
    
    printf("修改后:%s今年%d岁,考了%.1f分\n", p->name, p->age, p->score);
    
    return0;
}

用箭头操作符->,写起来简洁得不行!

玩法十二:指针数组做函数跳转表

这个玩法绝了,可以做个简易计算器:

#include <stdio.h>

float add(float a, float b) { return a + b; }
float sub(float a, float b) { return a - b; }
float mul(float a, float b) { return a * b; }
float div(float a, float b) { return a / b; }

int main() {
    float (*calc[])(float, float) = {add, sub, mul, div};
    char ops[] = {'+', '-', '*', '/'};
    
    float a = 10, b = 3;
    
    printf("简易计算器演示:\n");
    for(int i = 0; i < 4; i++) {
        printf("%.1f %c %.1f = %.2f\n", a, ops[i], b, calc[i](a, b));
    }
    
    // 输出:
    // 10.0 + 3.0 = 13.00
    // 10.0 - 3.0 = 7.00  
    // 10.0 * 3.0 = 30.00
    // 10.0 / 3.0 = 3.33
    
    return0;
}

把函数装进数组,想调哪个调哪个,是不是很酷?

玩法十三:const指针的三种姿势

const和指针组合,有三种不同的玩法:

#include <stdio.h>

int main() {
    int a = 10, b = 20;
    
    // 姿势1:指向常量的指针(指针可变,内容不可变)
    constint *p1 = &a;
    printf("p1指向:%d\n", *p1);  // 输出:10
    p1 = &b;  // 可以改指向
    printf("p1现在指向:%d\n", *p1);  // 输出:20
    // *p1 = 30;  // 这句会报错!不能修改内容
    
    // 姿势2:常量指针(指针不可变,内容可变)
    int * const p2 = &a;
    *p2 = 30;  // 可以修改内容
    printf("通过p2修改a:%d\n", a);  // 输出:30
    // p2 = &b;  // 这句会报错!不能改指向
    
    // 姿势3:指向常量的常量指针(都不能变)
    constint * const p3 = &a;
    printf("p3指向:%d\n", *p3);  // 只能读取
    // *p3 = 40;  // 报错!
    // p3 = &b;   // 报错!
    
    return0;
}

记住顺口溜:const在前内容定,const在后指针定,前后都有全都定!

玩法十四:指针与malloc的黄金组合

动态分配二维数组,这个操作太秀了:

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

int main() {
    int rows = 3, cols = 4;
    
    // 分配指针数组
    int **matrix = (int**)malloc(rows * sizeof(int*));
    
    // 为每一行分配空间
    for(int i = 0; i < rows; i++) {
        matrix[i] = (int*)malloc(cols * sizeof(int));
    }
    
    // 填充数据
    int count = 1;
    for(int i = 0; i < rows; i++) {
        for(int j = 0; j < cols; j++) {
            matrix[i][j] = count++;
        }
    }
    
    // 输出矩阵
    printf("动态二维数组:\n");
    for(int i = 0; i < rows; i++) {
        for(int j = 0; j < cols; j++) {
            printf("%2d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    // 释放内存
    for(int i = 0; i < rows; i++) {
        free(matrix[i]);
    }
    free(matrix);
    
    return0;
}

想要多大的二维数组就创建多大,用完就释放,内存管理变得超灵活!

玩法十五:回调函数——让函数"打电话"

这个玩法简直是编程界的社交达人!函数可以调用别的函数:

#include <stdio.h>

void sayHello() {
    printf("你好!\n");
}

void sayBye() {
    printf("再见!\n");
}

void greet(void (*callback)()) {
    printf("准备打招呼...\n");
    callback();  // 调用传进来的函数
    printf("招呼打完了!\n");
}

int main() {
    printf("=== 回调函数演示 ===\n");
    greet(sayHello);
    printf("\n");
    greet(sayBye);

    return0;
}

看到没?函数也能当参数传来传去,就像打电话一样!

玩法十六:链表——指针的终极大招

这个是指针的杀手锏应用,数据结构界的明星:

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

struct Node {
    int data;
    struct Node *next;// 指向下一个节点的指针
};

void printList(struct Node *head) {
    struct Node *current = head;
    printf("链表内容:");
    while(current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

int main() {
    // 创建三个节点
    struct Node *first = (struct Node*)malloc(sizeof(struct Node));
    struct Node *second = (struct Node*)malloc(sizeof(struct Node));
    struct Node *third = (struct Node*)malloc(sizeof(struct Node));

    // 填充数据并连接
    first->data = 10;
    first->next = second;

    second->data = 20;
    second->next = third;

    third->data = 30;
    third->next = NULL;

    printList(first);  // 输出:10 -> 20 -> 30 -> NULL

    // 释放内存
    free(first);
    free(second);
    free(third);

    return0;
}

链表就像火车,每节车厢都知道下一节在哪里!

玩法十七:指针与typedef的完美结合

给复杂的指针类型起个好听的名字:

#include <stdio.h>

// 给函数指针类型起个名字
typedef int (*MathFunc)(int, int);

// 给指向指针的指针起个名字  
typedefint** IntPtrPtr;

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

int main() {
    // 使用简化的类型名
    MathFunc operations[] = {add, mul};

    printf("加法:%d\n", operations[0](5, 3));  // 输出:8
    printf("乘法:%d\n", operations[1](5, 3));  // 输出:15

    // 二级指针的简化使用
    int num = 100;
    int *p1 = &num;
    IntPtrPtr p2 = &p1;

    printf("通过二级指针访问:%d\n", **p2);  // 输出:100

    return0;
}

复杂的类型有了简单的名字,代码瞬间清爽!

总结

看完这 17 个指针玩法,是不是觉得指针其实挺有意思的?

记住几个要点:

  • 指针就像一个地址本,记录着数据住在哪里
  • 加减运算让指针能在数组里自由跳跃
  • 函数指针让程序变得更加灵活
  • 动态内存让程序想要多少空间就有多少空间

最重要的是,多动手练习!纸上得来终觉浅,绝知此事要躬行。

下次再遇到指针,不要怕,把它当成你的好朋友,慢慢你就会发现,指针真的是C语言里最有趣的东西之一!

好了,今天的分享就到这里,记得点赞收藏哦!

↑↑↑ 点击领取6层板打样券 ↑↑↑ 


图片

END

作者:xiaokang1998

来源:跟着小康学编程

版权归原作者所有,如有侵权,请联系删除。

【声明】内容源于网络
0
0
芯片之家
1234
内容 1436
粉丝 0
芯片之家 1234
总阅读252
粉丝0
内容1.4k