欢迎光临
我们一直在努力

C语言指针从入门到精通 超详细保姆级教程

C语言指针从入门到精通 超详细保姆级教程

前言

指针是C语言的核心特性,也是C语言的精髓与难点,业内常说**“没掌握指针,就等于没学会C语言”**。指针的概念抽象、用法灵活,初学者极易踩坑,但它也是实现C语言高效内存操作、地址传递、数组/结构体/函数高级用法的关键。

本文从指针基础概念出发,由浅入深讲解指针的语法、运算、特殊指针、动态内存分配、多级指针,以及指针在数组、结构体、函数中的实际应用,同时整理了新手必看的避坑技巧和实操练习,适合C语言新手入门学习,也可作为进阶复习的参考资料,所有示例代码均可直接编译运行。

目录

  • 指针基础概念
  • 指针基础语法与核心操作
  • 指针运算与数组遍历
  • 结构体指针与->运算符
  • 特殊指针详解
  • 动态内存分配(malloc/calloc/realloc/free)
  • 多级指针与指针数组(易混点解析)
  • 指针在函数中的核心应用
  • 指针使用万能避坑技巧
  • 实操练习作业
  • 总结
  • 1 指针基础概念

    要理解指针,首先要搞懂内存地址和指针变量的关系,这是指针的核心本质。

  • 内存地址:计算机内存的最小存储单元是字节(8位),每个字节都有一个唯一的编号,这个编号就是内存地址。
    • 32位系统中,地址由32位二进制数构成,占4字节,通常用8位16进制数表示;
    • 64位系统中,地址占8字节,用16位16进制数表示。
  • 指针:C语言中专门用于保存内存地址的变量,简称“指针”。在不影响理解的前提下,指针、指针变量、地址可统称指针。
  • 指针的目标:指针变量中存储的地址为目标数据的首地址,指针的操作本质是对该首地址指向的内存空间中数据的操作。
  • 通俗类比:指针如同Windows系统的快捷方式,快捷方式保存了程序的实际存储路径,指针保存了数据的实际内存地址;通过快捷方式可打开程序,通过指针可操作对应地址的内存数据。
  • 2 指针基础语法与核心操作

    2.1 指针的定义语法

    指针的定义需指定指向的数据类型,语法格式:

    数据类型名 *指针变量名;

    关键说明:

    • 定义中的数据类型,是指针指向的内存空间的数据类型,而非指针变量本身的类型;
    • 指针变量本身的类型固定,且指针大小与指向的类型无关(64位系统固定8字节,32位系统固定4字节);
    • C语言官方推荐将*紧贴指针变量名书写。

    定义示例:

    char *s; // 定义指向char类型的指针s
    int *p; // 定义指向int类型的指针p
    float *f; // 定义指向float类型的指针f

    2.2 指针的两个核心运算符

    指针的操作依赖两个互为逆运算的运算符,是指针使用的基础,必须牢牢掌握:

    运算符名称作用举例说明
    & 取地址运算符 &num 获取变量num的内存地址
    * 解引用运算符 *p 获取指针p指向地址的实际数据

    2.3 指针的赋值与解引用(核心示例)

    指针的核心使用流程:定义指针变量 → 赋值(绑定内存地址) → 解引用(操作数据),示例代码如下(可直接运行):

    #include <stdio.h>
    int main() {
    int a = 10; // 定义普通int变量
    int *p = &a; // 取a的地址,赋值给指针p,p指向a
    printf("a的取值:%d\\n", a); // 直接访问a,输出10
    printf("*p的取值:%d\\n", *p); // 解引用p,访问指向的数,输出10
    printf("a的地址:%p\\n", &a); // 打印a的地址,%p为地址格式化符
    printf("p的取值:%p\\n", p); // p中存储的是a的地址,输出与&a一致

    *p = 20; // 解引用修改指向的内存数据,等价于a=20
    printf("修改后a的取值:%d\\n", a); // 输出20
    return 0;
    }

    2.4 指针变量的内存大小验证

    验证指针大小与指向类型无关的特性,代码示例:

    #include <stdio.h>
    int main() {
    int *p;
    char *q;
    float *f;
    // 64位系统输出均为8,32位系统输出均为4
    printf("sizeof(p) = %d\\n", sizeof(p));
    printf("sizeof(q) = %d\\n", sizeof(q));
    printf("sizeof(f) = %d\\n", sizeof(f));
    // 指向的类型大小不同,分别为4、1、4
    printf("sizeof(*p) = %d\\n", sizeof(*p));
    printf("sizeof(*q) = %d\\n", sizeof(*q));
    printf("sizeof(*f) = %d\\n", sizeof(*f));
    return 0;
    }

    3 指针运算与数组遍历

    指针支持算术运算和关系运算,其中算术运算是指针的核心应用,最常用的场景是数组遍历(C语言中数组名本质是数组的首地址,与指针天然契合)。

    3.1 指针的算术运算

    指针的算术运算并非简单的数值加减,而是基于指向的数据类型大小的偏移,核心运算规则如下(以int *p1、int *p2为例):

    运算表达式说明
    p1 + n 指针向地址增大的方向偏移n个数据大小(int偏移4*n字节)
    p2 – n 指针向地址减小的方向偏移n个数据大小(int偏移4*n字节)
    p2 – p1 计算两个指针之间间隔的数据个数(非字节数)
    p1++/++p1 指针向后偏移1个数据大小,遍历数组常用
    p2–/–p2 指针向前偏移1个数据大小,逆序遍历常用

    注意:不同数据类型的指针之间进行算术运算无实际意义;指针偏移后必须指向有效内存地址,否则会导致程序崩溃、获取垃圾值等未定义行为。

    算术运算示例:

    #include <stdio.h>
    int main() {
    int a = 1;
    int *p = &a;
    printf("初始地址:%p\\n", p); // 64位示例:0x7fffbf1c0b84
    p++;
    printf("p++后地址:%p\\n", p); // 偏移4字节:0x7fffbf1c0b88
    p += 2;
    printf("p+=2后地址:%p\\n", p); // 再偏移8字节:0x7fffbf1c0b94
    return 0;
    }

    3.2 指针的关系运算

    指针的关系运算用于判断两个指针在内存中的地址高低关系,支持>、<、>=、<=、==、!=六种运算符。 核心规则:

  • 只有指向同一内存区域的指针,关系运算才有实际意义(如同一数组的指针);
  • 指针可与NULL(0) 比较,用于判断指针是否为空,标准写法:if (NULL == p);
  • 指针与非0整数比较无意义,不同数据类型的指针比较无意义。
  • 3.3 指针遍历数组(核心应用)

    利用指针算术运算遍历数组,比数组索引更高效,是C语言开发的常用写法,支持一维数组和二维数组遍历。

    3.3.1 指针遍历一维数组

    #include <stdio.h>
    int main() {
    int arr[5] = {1,2,3,4,5};
    int *p = arr; // 数组名arr是首地址,直接赋值给指针p
    // 指针遍历:p < &arr[5] 表示未到数组末尾
    for (; p < &arr[5]; p++) {
    printf("%d ", *p); // 依次输出1 2 3 4 5
    }
    return 0;
    }

    3.3.2 指针遍历二维数组

    #include <stdio.h>
    int main() {
    // 4行5列二维数组
    int array[][5] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    int *start = array[0]; // 指向数组第一个元素
    int *end = array[0] + 19; // 指向数组最后一个元素
    // 遍历所有元素
    for (; start <= end; start++) {
    printf("%d ", *start);
    }
    return 0;
    }

    4 结构体指针与->运算符

    结构体指针是指向结构体变量的指针,用于操作结构体数据,C语言为结构体指针提供了专属的指向运算符->,替代繁琐的解引用写法,是开发中的必用语法。

    4.1 结构体指针的定义

    语法格式:

    struct 结构体名 *结构体指针名;

    定义示例:

    // 定义结构体
    struct Message {
    int number;
    char info[200];
    };
    // 定义结构体指针
    struct Message *p;

    4.2 结构体成员的两种访问方式

    结构体指针访问成员有两种方式,->是推荐写法,更简洁高效:

  • 基础写法:(*结构体指针名).成员名(必须加括号,因.优先级高于*);
  • 简洁写法:结构体指针名->成员名(指向运算符->,专为结构体指针设计)。
  • 核心示例:

    #include <stdio.h>
    #include <string.h>
    struct Message {
    int number;
    char info[200];
    };
    int main() {
    struct Message info = {1, "Hello C"};
    struct Message *p = &info; // 结构体指针指向info

    (*p).number = 2; // 基础写法,修改number
    strcpy(p->info, "Hello Pointer"); // 简洁写法,修改字符串
    // 两种方式访问成员,输出结果一致
    printf("number = %d\\n", (*p).number); // 输出2
    printf("info = %s\\n", p->info); // 输出Hello Pointer
    return 0;
    }

    5 特殊指针详解

    C语言中有几种特殊的指针类型,是新手的主要踩坑点,掌握其特性和用法,能有效避免程序的未定义行为。

    5.1 const指针(只读指针)

    const指针用于限制指针的修改权限,分为指向常量的指针、常量指针、指向常量的常量指针三种,记忆核心口诀:const在左,修饰内容;const在右,修饰指针。

    三种const指针的特性对比表:

    声明写法指针类型能否修改指针本身能否修改指向的数值
    const int *p; / int const *p; 指向常量的指针 可以 不可以
    int *const p; 常量指针 不可以 可以
    const int *const p; 指向常量的常量指针 不可以 不可以

    使用示例:

    #include <stdio.h>
    int main() {
    int a = 3, b = 5;
    int const *p = &a;
    a = 4; // 直接修改变量,合法
    p = &b; // 修改指针指向,合法
    // *p = 6; // 解引用修改数值,非法,编译报错
    printf("%d\\n", *p); // 输出5
    return 0;
    }

    5.2 void指针(无类型指针)

  • 概念:void *表示无类型指针,用于暂时无法确定指针指向的数据类型的场景;
  • 核心特性:void *可以赋值给任意类型的指针,但其他类型指针不能直接赋值给void指针(需强制类型转换);
  • 常用场景:C语言库函数(如malloc、memcpy)的返回值/参数,因无法预知用户的内存使用类型。
  • 示例:

    // malloc函数的原型,返回值为void*
    void* malloc(size_t size);
    // 使用时强制转换为指定类型
    int *num = (int*)malloc(sizeof(int));

    5.3 野指针(最危险的指针)

  • 概念:未初始化、或指向未知内存地址的指针,野指针的解引用会导致程序崩溃、内存污染等严重问题;
  • 产生原因:
    • 定义指针变量时未初始化;
    • 指针指向的内存释放后,未及时置空;
    • 指针偏移超出有效内存区域。
  • 避坑方法:定义指针时立即初始化(赋值为NULL),避免未绑定地址的指针解引用。
  • 错误示例:

    #include <stdio.h>
    int main() {
    int *p; // 未初始化,p为野指针
    // *p = 100; // 解引用野指针,编译/运行报错
    return 0;
    }

    5.4 空指针

  • 概念:明确指向无有效内存地址的指针,C语言中用NULL(本质是宏定义的0)表示;
  • 定义语法:int *p = NULL;;
  • 核心作用:作为指针的初始值,避免野指针;通过if (p == NULL)判断指针是否有效,是开发中的标准写法。
  • 5.5 悬垂指针(悬空指针)

  • 概念:指针指向的动态内存被free释放后,指针仍保留原地址,此时指针变为悬垂指针;
  • 危害:悬垂指针的解引用会访问已被释放的内存,导致程序未定义行为;
  • 避坑方法:free释放动态内存后,立即将指针置为NULL。
  • 正确示例:

    int *p = (int*)malloc(sizeof(int));
    free(p); // 释放动态内存
    p = NULL; // 立即置空,避免悬垂指针

    6 动态内存分配

    C语言中普通数组的大小是编译期固定的,无法根据运行时需求调整,而动态内存分配可在程序运行时申请/释放内存,实现内存的灵活使用。

    动态内存分配的函数均定义在stdlib.h头文件中,使用前需引入:#include <stdlib.h>,核心函数包括malloc、calloc、realloc,释放内存的函数为free。

    6.1 核心分配函数详解

    6.1.1 malloc函数

    功能:分配指定字节数的连续内存,不做任何初始化,内存中为随机垃圾值。 语法:

    void* malloc(size_t len); // len:需要分配的字节数

    使用示例:

    // 分配1个int类型的内存(4字节)
    int *num = (int*)malloc(sizeof(int));
    // 分配4个int类型的内存(16字节)
    int *nums = (int*)malloc(4 * sizeof(int));

    6.1.2 calloc函数

    功能:根据数据个数和单个数据字节数分配内存,自动将所有字节初始化为0,无需手动初始化。 语法:

    void* calloc(size_t num_elements, size_t element_size);
    // num_elements:数据个数;element_size:单个数据的字节数

    使用示例:

    // 分配1个int类型的内存,初始化为0
    int *num = (int*)calloc(1, sizeof(int));
    // 分配4个int类型的内存,全部初始化为0
    int *nums = (int*)calloc(4, sizeof(int));
    printf("%d\\n", *nums); // 输出0

    6.1.3 realloc函数

    功能:对已分配的动态内存进行扩容/缩容,自动将原内存的数据复制到新内存,释放旧内存。 语法:

    void* realloc(void *old_addr, size_t new_size);
    // old_addr:原动态内存的指针;new_size:新的内存字节数

    使用示例:

    int *nums = (int*)malloc(4 * sizeof(int));
    // 将内存扩容为8个int类型(32字节)
    nums = (int*)realloc(nums, 8 * sizeof(int));

    6.2 free函数(内存释放)

  • 功能:释放由malloc、calloc、realloc分配的动态内存,将内存归还给操作系统;
  • 语法:void free(void *ptr);;
  • 核心规则:
    • 动态内存不会被程序自动释放,必须手动调用free,否则会导致内存泄漏;
    • free仅释放内存,不会改变指针的值,释放后必须将指针置为NULL;
    • 不能多次释放同一块内存,不能释放非动态分配的内存(如局部变量、全局变量)。
  • 正确示例:

    int *p = (int*)malloc(sizeof(int));
    // 使用动态内存
    *p = 10;
    printf("%d\\n", *p);
    // 释放内存并置空
    free(p);
    p = NULL;

    6.3 malloc与calloc的核心区别

    特性malloccalloc
    参数形式 单个参数(总字节数) 两个参数(个数+单字节数)
    初始化 不初始化,内存为垃圾值 自动初始化为0
    性能 无初始化开销,性能更高 有初始化开销,性能稍低
    适用场景 通用场景,需手动初始化 整型/字符数组,无需手动初始化

    6.4 动态内存的初始化

    除了使用calloc,还可使用memset函数对动态内存进行初始化,memset定义在string.h头文件中,语法:

    void *memset(void *ptr, int value, size_t num);
    // ptr:内存首地址;value:初始化值(通常为0);num:初始化的字节数

    示例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main() {
    int *nums = (int*)malloc(4 * sizeof(int));
    memset(nums, 0, 4 * sizeof(int)); // 初始化为0
    printf("%d\\n", *nums); // 输出0
    free(nums);
    nums = NULL;
    return 0;
    }

    7 多级指针与指针数组(易混点解析)

    多级指针和指针数组是C语言指针的高频易混点,核心区别在于运算符优先级([]优先级高于*),掌握优先级即可快速区分。

    7.1 多级指针

  • 概念:指向指针变量的指针,即“指针的指针”,最常用的是二级指针,更高阶的三级/四级指针极少使用;
  • 二级指针定义语法:数据类型 **指针名;;
  • 核心关系:对于二级指针**q,*q是一级指针,**q是原数据。
  • 二级指针核心示例(带运行结果):

    #include <stdio.h>
    int main() {
    int m = 100;
    int *p = &m; // 一级指针,指向m
    int **q = &p; // 二级指针,指向p
    // 运行结果:m=100, &m=0xbff26ba4, p=0xbff26ba4, &p=0xbff26ba8
    printf("m=%d, &m=%p, p=%p, &p=%p\\n", m, &m, p, &p);
    // 运行结果:q=0xbff26ba8, &q=0xbff26bac, *q=0xbff26ba4, **q=100
    printf("q=%p, &q=%p, *q=%p, **q=%d\\n", q, &q, *q, **q);
    return 0;
    }

    核心等价关系:

    • *q == p == &m;
    • **q == *p == m。

    7.2 指针数组

  • 概念:数组的每个元素都是指针变量的数组,称为指针数组;
  • 定义语法:数据类型 *数组名[数组大小];([]优先级高于*,先结合数组名,构成数组);
  • 核心特性:指针数组的数组名是二级指针,因为其每个元素都是一级指针。
  • 定义示例:

    int *p[2]; // 包含2个int*类型指针的数组
    char *c[9]; // 包含9个char*类型指针的数组
    char *ps[5] = {"Beijing", "New York", "London", "Paris", "Moscow"}; // 字符指针数组

    字符指针数组使用示例:

    #include <stdio.h>
    int main() {
    char *ps[] = {"Beijing", "New York", "London", "Paris", "Moscow"};
    char **pps = ps; // 二级指针指向指针数组首地址
    for (int i = 0; i < 5; i++) {
    printf("%s\\n", pps[i]); // 依次输出所有字符串
    }
    return 0;
    }

    7.3 指针数组 VS 数组指针(核心易混点)

    数组指针是指向数组的指针,与指针数组的核心区别在于是否加括号(改变运算符优先级),两者对比表:

    类型定义写法本质运算特性
    指针数组 int *p[n]; 数组 p+1指向数组下一个元素
    数组指针 int (*p)[n]; 指针 p+1指向整个下一个数组

    关键说明:

    • int *p[n]:无括号,[]优先级高,p是数组,每个元素是int*指针;
    • int (*p)[n]:有括号,*先结合p,p是指针,指向长度为n的int型一维数组(行指针)。

    8 指针在函数中的核心应用

    指针在函数中的核心作用是实现地址传递,替代值传递的拷贝机制,既能直接修改函数外部的变量/数组/结构体,又能减少内存开销,提升程序效率。同时,指针还能实现指针函数、函数指针等高级用法,让函数调用更灵活。

    8.1 指针作为函数参数(地址传递)

    函数参数为指针时,传入的是变量/数组/结构体的内存地址,函数内部对指针的解引用操作,会直接修改外部的原始数据。这是指针在函数中最基础、最常用的用法,尤其适合数组、结构体等大数据类型的传递(避免拷贝开销)。

    8.1.1 传递一维数组

    两种等价写法(数组名本质是首地址,编译器会自动转换为指针):

    // 数组形式(编译器自动转为int*)
    int getArrayMax(int array[]) {
    return array[0];
    }
    // 指针形式(推荐,更直观)
    int getArrayMax(int *array) {
    return array[0];
    }

    8.1.2 传递二维数组

    二维数组的指针传递需指定列数,数组指针为必用写法:

    // 数组形式
    int getArrayMax(int array[][3]) {
    return array[0][0];
    }
    // 数组指针形式(推荐)
    int getArrayMax(int (*array)[3]) {
    return array[0][0];
    }

    8.1.3 传递指针数组

    指针数组的参数传递需使用二级指针,如main函数的标准参数:

    // 指针数组形式
    int main(int argc, char *argv[]) {
    // 业务逻辑
    }
    // 二级指针形式(等价)
    int main(int argc, char **argv) {
    // 业务逻辑
    }

    8.2 指针函数(返回值为指针的函数)

  • 概念:函数的返回值为指针类型的函数,称为指针函数;
  • 语法:数据类型 *函数名(参数列表) { … };
  • 核心作用:C语言不支持函数直接返回数组,通过指针函数可实现数组的返回效果(返回数组首地址);
  • 避坑要点:指针函数不能返回函数局部变量的地址(局部变量存于栈区,函数执行完毕后会被释放,导致返回悬垂指针)。
  • 指针函数核心示例(返回学生成绩数组):

    #include <stdio.h>
    // 指针函数:返回指向int数组的指针
    int *search(int (*p)[4], int n) {
    return *(p + n); // 返回第n行成绩的首地址
    }
    int main() {
    // 3个学生,4门课成绩
    int score[3][4] = {{60,70,80,90},{56,89,67,82},{78,90,66,100}};
    int n;
    printf("请输入查询的学生序号(1-3):");
    scanf("%d", &n);
    n; // 转换为数组下标
    int *a = search(score, n);
    printf("该学生的成绩为:");
    for (int i = 0; i < 4; i++) {
    printf("%d ", a[i]);
    }
    return 0;
    }

    8.3 函数指针(指向函数的指针)

  • 概念:指向函数入口地址的指针,函数名本质是函数的入口地址,可直接赋值给函数指针;
  • 核心作用:根据运行时条件灵活调用不同函数(如根据用户输入调用登录/注册函数),是实现回调函数的基础;
  • 定义语法:数据类型 (*函数指针名)(参数列表);(括号必须加,否则会被解析为指针函数);
  • 调用语法:函数指针名(实参列表); 等价于 函数名(实参列表);。
  • 核心规则:函数指针只能指向返回值类型、参数列表完全一致的函数,不能指向类型不匹配的函数;函数指针不支持算术运算(如p++、p+1)。

    函数指针核心示例(动态调用登录/注册函数):

    #include <stdio.h>
    // 定义两个待调用的函数
    void login() {
    printf("执行登录功能\\n");
    }
    void regist() {
    printf("执行注册功能\\n");
    }
    int main() {
    void (*func_ptr)(); // 定义无返回值、无参数的函数指针
    int choice = 2; // 模拟用户输入:1=登录,2=注册
    // 根据选择绑定函数指针
    if (choice == 1) {
    func_ptr = login;
    } else if (choice == 2) {
    func_ptr = regist;
    } else {
    printf("输入错误\\n");
    return 1;
    }
    func_ptr(); // 调用函数指针,输出:执行注册功能
    return 0;
    }

    8.4 函数指针数组

  • 概念:数组的每个元素都是函数指针的数组,称为函数指针数组,适合批量调用同类型函数;
  • 定义语法:数据类型 (*函数指针数组名[数组大小])(参数列表);;
  • 核心应用:计算器、菜单功能等需要批量调用同类型函数的场景。
  • 函数指针数组示例(实现加减运算):

    #include <stdio.h>
    // 定义两个同类型函数
    int plus(int a, int b) {
    return a + b;
    }
    int minus(int a, int b) {
    return a b;
    }
    int main() {
    // 定义函数指针数组,包含2个int(*)(int,int)类型的函数指针
    int (*pFunc[2])(int, int) = {plus, minus};
    // 调用数组中的函数
    printf("15+5=%d\\n", pFunc[0](15,5)); // 输出20
    printf("15-5=%d\\n", pFunc[1](15,5)); // 输出10
    return 0;
    }

    8.5 经典指针写法辨析

    为了方便记忆,整理了C语言中经典的指针相关写法,明确其本质:

    写法本质说明
    int *p 指向int型数据的一级指针
    int **p 指向int*型指针的二级指针
    int *p[3] 包含3个int*型指针的指针数组
    int (*p)[3] 指向长度为3的int型数组的数组指针(行指针)
    int (*p)(int,int) 指向返回int、参数为两个int的函数的函数指针
    int (*p[5])(int,int) 包含5个上述函数指针的函数指针数组

    9 指针使用万能避坑技巧

    指针的灵活度高,但出错代价大,以下6个避坑技巧是C语言开发的通用规范,建议刻进DNA,从根本上避免指针的未定义行为:

  • 初始化指针:定义指针时立即初始化,默认赋值为NULL,避免野指针:int *p = NULL;;
  • 检查动态内存分配结果:malloc/calloc/realloc可能分配失败(内存不足),返回NULL,必须检查:int *p = (int*)malloc(sizeof(int));
    if (p == NULL) { // 处理分配失败
    return 1;
    }
  • 解引用前验证指针:解引用指针前,必须判断指针是否为NULL,确保指向有效内存:if (p != NULL) {
    *p = 10;
    }
  • 避免指针越界:操作数组指针时,严格控制指针的偏移范围,不超出数组的首/尾地址;
  • free后立即置空:释放动态内存后,立即将指针置为NULL,避免悬垂指针:free(p); p = NULL;;
  • 禁止重复释放:释放内存前判断指针是否为NULL,避免多次释放同一块内存:if (p != NULL) {
    free(p);
    p = NULL;
    }
  • 10 实操练习作业

    指针的掌握离不开实战,以下练习覆盖指针的核心应用场景,建议独立完成,巩固所学知识:

  • 利用指针倒序遍历一个整型数字数组;
  • 用指针将整型数组s[8]={1,2,3,4,5,6,7,8}中的值逆序存放(原地修改);
  • 用指针实现:将字符串"Computer Science"赋给字符数组,从第一个字符开始间隔输出该字符串;
  • 定义商品结构体(包含名称、库存、价格),预定义3个商品数据,用指针作为函数参数实现商品按价格排序并输出;
  • 用指针模拟strcat函数的功能,实现两个字符串的拼接;
  • 定义一个字符串指针数组,用指针遍历找到字符长度最长的字符串并输出其长度;
  • 定义字符串指针数组char *words[4]={"aabbcc","admin","aaahhh","halo"},用指针统计数组中字符a出现的总次数。
  • 11 总结

    指针是C语言的核心,也是C语言高效、灵活的根源,其本质是对内存地址的操作。学习指针的关键不在于死记语法,而在于理解内存地址与指针变量的关系,并通过大量实操掌握其用法。

    本文从基础概念到高级应用,全面讲解了指针的核心知识点,核心总结如下:

  • 指针的核心是保存内存地址,&取地址、*解引用是指针的基础操作;
  • 指针运算的本质是基于数据类型的内存偏移,最常用的场景是数组遍历;
  • 结构体指针的->运算符是开发中的必用语法,简洁高效;
  • const指针、空指针、野指针、悬垂指针是新手踩坑点,掌握其特性可有效避坑;
  • 动态内存分配需牢记申请-使用-释放-置空的流程,避免内存泄漏;
  • 指针数组与数组指针的区别在于运算符优先级,函数指针与指针函数的区别在于括号;
  • 指针在函数中的核心是地址传递,可实现外部数据修改、灵活调用函数等高级功能;
  • 指针使用的核心原则是:始终保证指针指向有效内存,避免未定义行为。
  • 指针的学习没有捷径,多思考、多敲代码、多调试是唯一的方法。建议在学习过程中结合调试工具(如GDB)观察指针的地址变化和数据操作,加深对指针的理解。

    相关推荐

    • C语言内存管理(栈区/堆区/全局区)详解
    • C语言字符串与指针的结合使用
    • GDB调试指针的实用技巧
    • C语言指针经典面试题解析

    标签:C语言 | C语言指针 | 编程入门 | 后端开发 | C语言进阶 | 内存管理

    赞(0)
    未经允许不得转载:171主机测评 » C语言指针从入门到精通 超详细保姆级教程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址