c语言 指针变量总结,C语言指针知识点总结

C语言指针知识点总结

1.指针的使用和本质分析

(1)初学指针使用注意事项

1)指针一定要初始化,否则容易产生野指针(后面会详细说明);

2)指针只保存同类型变量的地址,不同类型指针也不要相互赋值;

3)只有当两个指针指向同一个数组中的元素时,才能进行指针间的运算和比较操作;

4)指针只能进行减法运算,结果为同一个数组中所指元素的下表差值。

(2)指针的本质分析

①指针是变量,指针*的意义:

1)在声明时,*号表示所声明的变量为指针。

例如:int n = 1; int* p = n;

这里,变量p保存着n的地址,即p—n,*p—n

2)在使用时,*号表示取指针所指向变量的地址值。

例如:int m = *p;

②如果一个函数需要改变实参的值,则需要使用指针作为函数参数(传址调用),如果函数的参数数据类型很复杂,可使用指针代替。

最常见的就是交换变量函数void swap(int* a, int* b)

③指针运算符*和操作运算符的优先级相同

例如:int m = *p++;

等价于:int m= *p; p++;

2.指针和数组

(1)指针、数组、数组名

如果存在一个数组 int m[3] = {1,2,3};

定义指针变量p,int *p = m(这里m的类型为int*,a[0]==int*)

这里,

其中,m为数组的地址,m为数组0元素的地址,两者相等,但意义不同,例如:

m+1 = (unsigned int)m + sizeof(*m)

m+1= (unsigned int)(m) + sizeof(*m)

=(unsigned int)(m) + sizeof(m)

m+1表示数组的第1号元素,m+1指向数组a的下一个地址,即数组元素“3”之后的地址。

等价操作:

m[i]←→*(m+i)←→*(i+m)←→i[m]←→*(p+i)←→p[i]

实例测试如下:

1 #includestdio.h

2

3 int main()

4 {

5 int m[3] = { 1,2,3 };

6 int *p = m;

7

8 printf(" m = %p\n", m);

9 printf(" m = %p\n", m);

10 printf("\n");

11

12 printf(" m+1 = %p\n", m + 1);

13 printf(" m[2] = %p\n", m[2]);

14 printf(" m+1 = %p\n", m + 1);

15 printf("\n");

16

17 printf(" m[1] = %d\n", m[1]);

18 printf(" *(m+1) = %d\n", *(m + 1));

19 printf(" *(1+m) = %d\n", *(1 + m));

20 printf(" 1[m] = %d\n", 1[m]);

21 printf(" *(p+1) = %d\n", *(p + 1));

22 printf(" p[1] = %d\n", p[1]);

23

24 return 0;

25 }

输出结果为:

(2)数组名注意事项

1)数组名跟数组长度无关;

2)数组名可以看作一个常量指针;所以表达式中数组名只能作为右值使用;

3)在以下情况数组名不能看作常量指针:

- 数组名作为sizeof操作符的参数

-数组名作为运算符的参数

(3)指针和二维数组

一维数组的指针类型是 Type*,二维数组的类型的指针类型是Type*[n]

(4)数组指针和指针数组

①数组指针

1)数组指针是一个指针,用于指向一个对应类型的数组;

2)数组指针的定义方式如下所示:

int (*p)[3] = m;

②指针数组

1)指针数组是一个数组,该数组里每一个元素为一个指针;

2)指针数组的定义方式如下所示:

int* p[5];

3.指针和函数

(1)函数指针

函数的本质是一段内存中的代码,函数的类型有返回类型和参数列表,函数名就是函数代码的起始地址(函数入口地址),通过函数名调用函数,本质为指定具体地址的跳转执行,因此,可定义指针,保存函数入口地址,如下所示:

int funcname(int a, int b);

int(*p)(int a, int b) = funcname;

上式中,函数指针p只能指向类型为int(int,int)的函数

(2)函数指针参数

对于函数int funcname(int a, int b);

普通函数调用int funcname(int, int),只能调用函数int func(int, int)

函数指针调用 intname(*func)(int,int),可以调用任意int(int,int)类型的函数,从而利用相同代码实现不同功能,

实例测试如下,假设有两个相同类型的函数func1和func2:

1 int func1(int a, int b, int c)

2 {

3 return a + b + c;

4 }

5

6 int func2(int a, int b, int c)

7 {

8 return a - b - c;

9 }

普通函数调用和函数指针调用方式及结果如下所示

1 printf("普通函数调用\n");

2 printf("func1 = %d\n", func1(100, 10, 1));

3 printf("func2 = %d\n", func2(100, 10, 1));

4 printf("\n");

5

6 printf("函数指针调用\n");

7 int(*p)(int, int, int) = NULL;

8 p = func1;

9 printf("p = %d\n", p(100, 10, 1));

10 p = func2;

11 printf("p = %d\n", p(100, 10, 1));

12 printf("\n");

需要注意的是,数组作为函数参数的时候,会变为函数指针参数,即:

int funcname( int m[] )——int funcname ( int* m );

调用函数时,传递的是数组名,即

funcname(m);

(3)回调函数

利用函数指针,可以实现一种特殊的调用机制——回调函数。回调函数是指把需要调用的函数指针作为参数传递给另一个函数,这个指针会在适当的时机被用来调用其所指向的函数,该函数指针指向的函数可能有多个,这种机制具有非常大的灵活性。

所谓的回调指的是,上层调用底层,底层又回来调用上层,回调函数的机制:

1)调用者不知道需要调用的具体函数

2)被调用的函数不知道何时会被调用

3)在满足特定条件时,调用者通过函数指针调用被调用的函数

一个简单的回调函数的例子如下所示:

1 #includestdio.h

2

3 int func1(int a, int b)

4 {

5 int num = 2 * a * b;

6 printf("func1的num = %d\n", num);

7 return num;

8 }

9

10 int func2(int a, int b)

11 {

12 int num = 4 * a * b;

13 printf("func2的num = %d\n", num);

14 return num;

15 }

16

17 //回调函数

18 int callback(int(*p)(int, int))

19 {

20 int a = 3, b = 2;

21 return p(a, b);

22 }

23

24 int main()

25 {

26 callback(func1);

27 callback(func2);

28 }

运行结果如图所示:

可以看出,如果不使用函数指针,而使用普通函数调用,则无法使用callback函数来调用func1和func2两个函数。

4.指针和常量

int const* p ; (指针p本身是变量,p指向的数据为常量)

int* const p;(指针p本身是常量,p指向的数据为变量)

const int* p;(指针p本身是变量,p指向的数据为常量)

const int* const p;(指针p和p指向的数据都是常量)

C语言指针知识点总结 相关文章

MySQL知识点

iwehdio的博客园:https://www.cnblogs.com/iwehdio/ 1、SQL MySQL(一)——CRUD语句 查询: select 查询列表 from 表名 select distinct 查询列表 from 表名 select 查询列表 from 表名 where 筛选条件 select 查询列表 from 表名 order by 排序列表 ASC/D

Leetcode 88. 合并两个有序数组 双指针

地址https://leetcode-cn.com/problems/merge-sorted-array/ 给你两个有序整数数组nums1 和 nums2,请你将 nums2 合并到nums1中,使 nums1 成为一个有序数组。初始化nums1 和 nums2 的元素数量分别为m 和 n 。你可以假设nums1 的空间大小等于m + n,这样它就

c语言中录入指定人数成绩、统计成绩分布

1、 #include stdio.h# define NUMBER 80int main(void){ int a[NUMBER]; int number; puts("please input the number of the student."); do { printf("number of student = "); scanf("%d", number); if (number 1 | number NUMBER) { printf("\athe san o

用C语言给NI数据采集卡编程序实现多路数据的同时采集

因为写的上一篇NI数据采集卡的程序有人留言说想要实现多路数据的同时采集,我没有及时回复,深感抱歉,在此写一篇关于NI数据采集卡的多路数据同时采集的程序 第一个程序实现的功能:六路数据同时采集,采集有限个数据,并且保存到txt文档中。采用的是参考单

本周阅读打卡--c++设计新思维-智能指针

新在哪里 只有c++语言有关系,不会涉及其他知识。 适合对象: After reading this chapter, you will be an expert in smart pointer issues such as the following: 阅读后的收益: smart 具备value语义,你可以对放心的其拷贝和复制操作。指针不行 其他函

jvm相关知识

编程语言最终是如何去调用CPU的? 像java、c、c++、python等都属于高级语言,而高级语言是通过调用汇编语言,而汇编语言内部封装了很多操作指令,比如 add sub等,去操作机器指令,像cpu不同的型号或类型都有不同的指令,比如x86,x64是不一样,所以对应的机

C 程序关于时间和日期的操作详解

在平时的 C 语言编程中,经常会遇到关于时间和日期的相关操作。时间日期的操作其实并不难也不复杂,但是作为程序员还是必须要熟练掌握相关操作的,就像对待字符串和内存操作一样。 1. time_t 类型时间 在 C 语言中可以用 time_t 类型表示时间,time_t 类型时

js 冒泡排序

排序前需要了解的知识点:如何交换两个变量的值 交换变量位置案例 var a = 12,b = 54;//使用中间变量方式var temp; //创建个中间变量temptemp = a; //先将 a 的值给temp, 此时temp = 12a = b; //再把 b 的值给到 a,此时 a = 54b = temp; //最后把temp的值给

Electron实用技巧-electron-builder中用户协议(license)的使用及多语言支持

# 1 通常pc软件的安装过程中,会加入用户协议,如: 下面介绍一下使用 electron-builder 打包应用,如何加入license。首先参考官网介绍:windows: nsis[1] ,macOS: dmg[2] # 2 官网上关于license配置说明写的不是很详细,下面是我实践总结出的正确的姿势

Java面试特殊知识点总结 part1

并发与多线程main方法里没有创建新的线程,执行main方法一共需要几个线程? 可以使用 ManagementFactory 的 getThreadMXBean 方法获取 ThreadMXBean 信息,进而获取线程信息进行查看。代码: package Exercise;import java.lang.management.ManagementFactory

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值