嗨喽,大家好,我是程序猿老王,程序猿老王就是我。
        今天给大家讲一讲C语言指针。

目录

一、指针的由来

二、指针应用

三、指针含义

四、指针定义

五、指针初始化

六、指针解引用

七、指针运算

八、指针与数组

九、指针与结构体

十、指针与函数

十一、函数指针

十二、总结

十三、常见问题

Q1: 什么是野指针?

Q2: 什么是空指针?

Q3: 什么是指针常量?

Q4: 什么是常量指针?

Q5: 什么是指向指针的指针?


一、指针的由来

指针的概念最早出现在计算机科学的早期阶段,当时计算机的内存非常昂贵,而且存储器容量很小,程序员需要尽可能地利用每一个内存单元。
        在那个时代,程序员需要手动操作内存,这样可以更高效地使用内存和控制程序的执行。指针的概念就是在这个时期被引入的,它允许程序员直接操作内存地址,这样可以更高效地使用内存和处理数据。
        C语言是在20世纪70年代由贝尔实验室的Dennis Ritchie和他的同事开发的,C语言是一种系统编程语言,被广泛应用于操作系统、编译器、网络协议、嵌入式系统等领域。C语言的指针特性使得它非常适合对底层硬件进行控制和优化,同时也可以实现高级数据结构和算法,是一门非常强大的编程语言。

二、指针应用

在C语言中,指针被广泛应用于数据结构和算法中。例如,使用指针可以很方便地实现链表、树、图等数据结构,也可以实现常见的排序和查找算法,如快速排序、归并排序、二分查找等。
另外,指针还可以用于动态内存分配和释放,这是一种非常灵活的内存管理方式。在程序运行时,可以通过指针动态地分配内存,这样可以避免在编译时就分配过多的内存,从而节省内存空间。使用完内存后,还可以通过指针释放内存,这样可以避免内存泄漏和程序运行缓慢等问题。
        除了这些应用,指针还可以用于函数的参数和返回值。通过使用指针作为函数参数,可以避免在函数调用时复制大量的数据,从而提高程序的执行效率。通过使用指针作为函数返回值,可以实现复杂的返回值类型,如数组、结构体等,从而实现更加灵活和高效的程序设计。
        总之,指针是C语言的核心特性之一,它提供了一种高效、灵活的内存管理方式,可以实现很多高级的数据结构和算法。虽然指针也带来了一些问题和挑战,但只要小心使用,指针仍然是一种非常有用的编程工具。

三、指针含义

指针是C语言中一种重要的数据类型,用于存储和操作内存地址。指针变量本身存储的是内存地址,而不是实际的数据值。通过指针变量可以访问和操作内存中的数据。

四、指针定义

指针的定义包括两个部分:

  • 指针类型
  • 指针变量名
    指针类型指定了指针所指向的数据类型,例如int类型的指针可以指向整型数据,char类型的指针可以指向字符数据,等等。指针类型的声明使用*符号,例如:
int *p;      // 定义一个指向int类型的指针变量p
char *s;     // 定义一个指向char类型的指针变量s

指针变量名是一个标识符,用于标识指针变量,例如:

int *p;     // 定义一个指向int类型的指针变量p
int *count; // 定义一个指向int类型的指针变量count

五、指针初始化

指针变量必须先初始化,才能使用。指针变量的初始化可以使用地址运算符&,将一个变量的地址赋给指针变量,例如:

int x = 10; // 定义一个整型变量x,并赋值为10
int *p;     // 定义一个指向int类型的指针变量p
p = &x;     // 将变量x的地址赋给指针变量p

上面的代码将变量x的地址赋给了指针变量p,使得p指向了变量x。
        指针变量还可以初始化为NULL,表示指针不指向任何有效的内存地址。NULL是C语言标准库中定义的一个宏,其值为0,例如:

int *p = NULL; // 定义一个指向int类型的指针变量p,初始化为NULL

六、指针解引用

指针变量存储的是一个地址,如果要访问该地址指向的数据,需要使用指针的解引用操作符*,例如:

int x = 10;         // 定义一个整型变量x,并赋值为10
int *p;             // 定义一个指向int类型的指针变量p
p = &x;             // 将变量x的地址赋给指针变量p
printf("%d\n", *p); // 输出变量x的值,应该输出10

上面的代码使用指针的解引用操作符*,访问了指针变量p所指向的地址的数据,输出了变量x的值。

七、指针运算

指针变量也可以进行运算。指针运算有两种:指针的自增和指针的加减运算。
        指针的自增运算符++会将指针变量的值增加指针类型所指向的数据类型的字节数,例如:

int arr[] = {1, 2, 3, 4, 5};
int *p = arr; // 将数组的第一个元素的地址赋给指针变量p
p++;          // 指针自增,p指向数组的第二个元素

指针的加减运算会将指针变量的值加上或减去指定的偏移量,偏移量的单位是指针类型所指向的数据类型的字节数,例如:

int arr[] = {1, 2, 3, 4, 5};
int *p = arr; // 将数组的第一个元素的地址赋给指针变量p
p += 2;       // 指针加2,p指向数组的第三个元素

需要注意的是,指针运算的结果必须指向有效的内存地址,否则会引发错误。

八、指针与数组

在C语言中,数组名是一个指向数组第一个元素的指针常量,可以用数组名来初始化指针变量,例如:

int arr[] = {1, 2, 3, 4, 5};
int *p = arr;    // 将数组的第一个元素的地址赋给指针变量p

这里将数组名arr赋给指针变量p,p指向了数组的第一个元素。
        指针也可以像数组一样访问数组的元素,使用指针变量名和下标来访问元素,例如:

int arr[] = {1, 2, 3, 4, 5};
int *p = arr;            // 将数组的第一个元素的地址赋给指针变量p
printf("%d\n", p[2]);    // 输出数组的第三个元素,应该输出3

上面的代码使用了指针变量名和下标来访问数组的第三个元素。

九、指针与结构体

指针在C语言中还可以用于操作结构体。结构体是一种用户自定义的数据类型,它可以将多个不同类型的数据组合成一个整体,从而方便程序的设计和管理。结构体通常包含多个成员,每个成员可以是不同的数据类型,如整型、字符型、数组、指针等。
        使用指针可以更加方便地操作结构体。在C语言中,结构体变量可以被看作是一段连续的内存空间,结构体成员的地址是相对于结构体变量地址的偏移量。因此,可以通过指针来访问结构体的成员,这样可以方便地修改结构体的内容和实现结构体的操作。
        例如,下面是一个简单的结构体类型的定义:

struct Person {char name[20];int age;float height;float weight;
};

使用指针可以方便地操作结构体变量,例如:

struct Person p = {"Alice", 20, 170.0, 60.0};
struct Person *p_ptr = &p;
p_ptr->age = 21;

在上面的代码中,首先定义了一个Person类型的结构体变量p,然后定义了一个指向p的指针p_ptr。通过p_ptr->age的方式,可以方便地访问和修改结构体变量p的成员age
        除了结构体的成员,指针还可以指向整个结构体变量。例如,可以通过指针动态地分配结构体变量的内存,并返回指针,实现灵活的内存管理。例如:

struct Person *p_ptr = (struct Person *) malloc(sizeof(struct Person));
p_ptr->age = 21;

在上面的代码中,首先通过malloc函数动态地分配了一个Person类型的结构体变量的内存,然后将返回的指针转换成了struct Person类型的指针p_ptr,并设置了p_ptr->age的值。

十、指针与函数

指针在函数参数传递中使用非常广泛,通过传递指针,函数可以修改调用者的数据。在函数声明中,使用指针类型来指定函数参数是指针类型,例如:

void func(int *p);

上面的代码声明了一个函数func,它接受一个指向int类型的指针变量p作为参数。
        在函数定义中,使用指针变量名来访问指针所指向的数据,例如:

void func(int *p) {*p = *p + 1;    // 修改指针所指向的数据
}

上面的代码定义了一个函数func,它接受一个指向int类型的指针变量p作为参数,在函数体中使用*p来访问指针所指向的数据,并将其加1。
        在调用函数时,将指向数据的指针作为参数传递给函数,例如:

void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}int main() {int x = 1, y = 2;swap(&x, &y);printf("x = %d, y = %d\n", x, y);return 0;
}

上面的代码定义了一个swap函数,通过指针参数a和b可以交换它们所指向的变量的值。在主函数中,调用swap函数时将x和y的地址作为参数传递进去,从而实现了交换x和y的值的效果。
        指针还可以用来返回函数的结果。例如,可以定义一个函数来查找数组中的最大值,并返回指向最大值的指针,例如:

int *findMax(int *arr, int size) {int *max = arr;for (int i = 0; i < size; i++) {if (arr[i] > *max) {max = &arr[i];}}return max;
}

上面的代码定义了一个函数findMax,它接受一个指向int类型的数组和数组大小作为参数,并返回一个指向最大值的指针变量。
        在函数中,使用指针变量max来记录数组中最大值的位置。遍历数组,如果找到了比当前最大值更大的元素,就将max指向该元素的位置。最后,函数返回指向最大值的指针max。
        在调用函数时,将指向数组的指针和数组大小作为参数传递给函数,并使用返回的指针来访问最大值,例如:

int arr[] = {5, 2, 9, 4, 7};
int size = sizeof(arr) / sizeof(int);
int *p = findMax(arr, size);    // 调用函数,返回指向最大值的指针
printf("%d\n", *p);             // 输出最大值,应该输出9

上面的代码创建了一个int类型的数组arr,并使用sizeof运算符计算数组大小。然后调用函数findMax,将指向数组的指针arr和数组大小size作为参数传递给函数。函数会返回指向最大值的指针p,最后程序会输出最大值9。

十一、函数指针

函数指针是指向函数的指针变量,可以用来调用该函数。在C语言中,函数指针可以作为参数传递给其他函数,可以用来实现回调函数和动态函数调用等高级特性。
        例如,定义一个遍历整数数组的函数traverse,可以使用函数指针作为回调函数参数,实现遍历数组并执行回调函数的功能:

void print(int x) {printf("%d ", x);
}void traverse(int *arr, int size, void (*callback)(int)) {for (int i = 0; i < size; i++) {callback(arr[i]);}
}int main() {int arr[] = {1, 2, 3, 4, 5};traverse(arr, 5, print);return 0;
}

在traverse函数中,callback是函数指针类型的参数,通过函数指针可以调用回调函数。在调用traverse函数时,使用print函数作为回调函数参数,实现遍历数组并输出元素的功能。

十二、总结

指针是C语言中的重要概念,它提供了一种灵活的方式来访问内存中的数据。指针变量存储了内存地址,可以用来访问变量、数组、结构体等数据类型。指针运算可以用来遍历数组、字符串等数据结构,以及动态分配内存。指针还可以用来传递函数参数和返回函数结果,它是C语言中的重要工具之一。

十三、常见问题

Q1: 什么是野指针?

A1: 野指针是指一个指针变量指向未知的内存地址,也就是没有被初始化的指针变量。使用野指针会导致不可预期的行为,包括程序崩溃等问题。因此,我们应该在定义指针变量时,给它一个合法的初始值,或者将它初始化为NULL。

Q2: 什么是空指针?

A2: 空指针是指一个指针变量指向空地址,也就是NULL常量。空指针在C语言中有重要的作用,它常常用来表示指针变量没有指向任何有效的内存地址。使用空指针时需要注意,因为它不能被解引用。

Q3: 什么是指针常量?

A3: 指针常量是指一个指针变量的值不能被改变,但是指向的数据可以被改变。在定义指针常量时需要使用const关键字,例如:

int num = 10;
const int *p = &num;

上面的代码定义了一个指针常量p,它指向int类型的数据,但是p的值不能被改变。这意味着,p不能被用来指向其他的地址,但是可以通过p来访问所指向的数据。

Q4: 什么是常量指针?

A4: 常量指针是指一个指针变量指向的地址不能被改变,但是指向的数据可以被改变。在定义常量指针时需要使用const关键字,例如:

int num1 = 10;
int num2 = 20;
int *const p = &num1;
*p = 100;     // 合法,可以修改指向的数据
p = &num2;    // 非法,不能修改指向的地址

上面的代码定义了一个常量指针p,它指向int类型的数据,但是p指向的地址不能被改变。这意味着,p不能被用来指向其他的地址,但是可以通过p来访问所指向的数据。

Q5: 什么是指向指针的指针?

A5: 指向指针的指针,也就是二级指针,是指一个指针变量存储的是另一个指针变量的地址。在C语言中,我们可以使用二级指针来实现对二维数组的动态内存分配。例如:

int **arr;
arr = (int **)malloc(10 * sizeof(int *));
for (int i = 0; i < 10; i++) {arr[i] = (int *)malloc(10 * sizeof(int));
}

上面的代码动态分配了一个10行10列的二维数组,其中arr是一个二级指针,指向一个一维指针数组,而每个一维指针又指向一个整型数组。

---END---


        关于更多嵌入式C语言、FreeRTOS、RT-Thread、Linux应用编程、linux驱动等相关知识,关注公众号【嵌入式Linux知识共享】,后续精彩内容及时收看了解。

C语言入门阶段08:C语言指针相关推荐

  1. C语言入门(初识C语言)

    C语言入门(初识C语言) 前言 什么是C语言? 为什么选择C语言? 计算机语言的发展 高级计算机语言中的经典:C语言 初识C语言(正片开始) 一.第一个C语言程序(你好,C语言) 1.1 #inclu ...

  2. 怎么理解python语言_Python语言入门1-理解Python语言

    本文主要向大家介绍了Python语言入门的理解Python语言,通过具体的内容向大家展现,希望对大家学习Python语言入门有所帮助. python是解释型的脚本语言 解释型语言 与C/C++等编译型 ...

  3. 计算机c语言入门.ppt,计算机c语言入门经典

    计算机c语言入门经典 C语言对编写需要进行硬件操作的场合,优于其它高级语言.小编为大家分享一些计算机c语言入门经典,欢迎参考! 一.开始之前 FAQ 那是什么 为何有这篇FAQ 编程为何物 如果这就是 ...

  4. c语言入门经典doc,C语言入门经典C语言编程.ppt

    C语言入门经典C语言编程.ppt 第01章 C语言编程,C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序即一组指令,并让计算机依指令行事 ...

  5. C语言入门教程学习 C语言学习包括哪些?

    嵌入式开发有一定了解的朋友们知道是在操作系统内部开发的,对于操作系统内部来说基本上都是用C语言来进行编译的,所以说对于C语言的学习在嵌入式开发过程中是非常重要的.下面就给大家介绍一些C语言入门教程的相 ...

  6. C语言入门篇 初识C语言

    C语言入门篇主要包含内容有:一.分支和循环语句 二.函数 三.数组 四.操作符 .五.指针 .六.结构体 七.函数栈帧的创建和销毁 目录 1.编写第一个程序 2.数据类型 3.变量 4.常量 5.字符 ...

  7. c语言入门教程文库,C语言入门教程(全集)课件

    C语言入门教程(全集)课件 01123364105 Y N p AB X=0? YN P1 A A P2 a a b b Y Y N N y n A B P A A B X=0? 3 a97 3 U ...

  8. c语言入门经典案例,c语言入门经典案例及飞源代码.doc

    c语言入门经典案例及飞源代码 循环控制输出图案 [程序1]题目:输出9*9口诀.1.程序分析:分行与列考虑,共9行9列,i控制行,j控制列.2.程序源代码:#include "stdio.h ...

  9. vhdl语言入门_初学Chisel语言,看这篇就够了:最方便简洁的入门资料整理

    声明:本文是我一个很优秀的学生总结的,放出来供广大chisel语言爱好者参考. Chisel(Constructing Hardware In a Scala Embedded Language)是U ...

最新文章

  1. SVO学习笔记(一)
  2. 独家 | ARIMA/Sarima与LSTM的时间序列数据集成学习(附链接)
  3. LinkedList实现原理
  4. sklearn 安装_sklearn-classification_report
  5. 求计算机技术在创新上的应用,计算机技术在教学上的应用
  6. 测试面试题集-3.生活物品测试:行李箱、电梯、洗衣机
  7. java迭代法求圆周率用梯形_感悟数学“近似计算”之美——“望星楼”里的圆周率...
  8. cmd长ping记录日志和时间_ping记录带时间戳
  9. 2021年值得推荐的几个可视化软件
  10. python自动生成采集规则_python 织梦自动采集更新脚本
  11. vscode下载提速方法
  12. 高等数学(第七版)同济大学 习题1-2 个人解答
  13. Kali 暴力破解wifi密码
  14. nuxt 如何添加robots.txt文件
  15. SAP ABAP BDC调用
  16. 笔记本重装系统后office没了
  17. sql查询结果加上序号
  18. 解决电脑端微信浏览器不支持vue、axios等问题
  19. 什么是软文推广?如何才能把软文推广的更好呢?
  20. IE 调试工具 IETester+DebugBar

热门文章

  1. jQuery中的end()的定义与用法
  2. 反编译获取apk安装包源代码步骤
  3. 时钟表24进制HTML,24进制数字电子钟时计器、译码显示电路 具有自动清零功能
  4. Apifox 测试工具
  5. linux- 日志管理
  6. 天文学 python_4个天文学入门Python工具
  7. H5一键复制 兼容iOS
  8. git基本命令行操作
  9. 干货!如何在训练中自动识别数据中潜在的不同分布并自适应?——以空间数据为例,应用不限于空间数据...
  10. JPA 概述及 SpringDataJpa 框架基本使用指南