数组传参的特殊性,数组指针,函数指针
来源:互联网 发布:胶州加工中心编程招聘 编辑:程序博客网 时间:2024/06/08 08:57
- - - - - - - - - - - - - - - 触控未来的日子–Day 41- - - - - - - - - - -
早会,闫梦州,诗朗诵。《假如生活欺骗了你》–普希金。
今日笑梗:“我不困,我只是趴一下。”—-叶瑞达
昨天遗漏的知识点:
#include<stdio.h>void fun(int *p){ printf("%d\n",p[5]); getchar();}void main(){ int a[10] = {1,2,3,4,5,6,7,8,9,10}; fun(&a[3]);}
上述代码中:p[i],相当于将传进去的地址,像后偏移5位后取值。
改变一级指针的指向(直接改变):
void main2(int * p )
{
int *p2 = p;(int *p2; p2 = p)
*p2 = 100;
}
通过二级指针改变一级指针的指向(间接改变):
void main1(int *p)
{
int **p = &p;
**p = 200;
}
- - - - - - - - - - - - - - - - - -今日内容 - - - - - - - - - - - - - - - - - - - - -
数组传参特殊性:
在此之前我们知道形参值的改变不会影响实参的值,但是数组是个例外。当数组作为参数传递给函数时,形参并没有另外开辟空间,而是直接在原数组的地址上操作。如果函数内更改了数组元素的值,那么原函数也会修改,这样是为了节省内存。代码演示如下:
#include<stdio.h>int i =0;void print(int a[]) { for(i = 0;i < 5;i++) { printf("%d\n",a[i]); //1,3,9,11,23 } a[2] = 100;}void main(){ int a[5] = {1,3,9,11,23}; print(a); for(i = 0;i < 5;i++) { printf("%d\n",a[i]); //1,3,100,11,23 } getchar();}
数组指针
前方有坑,需要注意
int a[2][3] = {{1,2,3},{4,5,6}};
a,指向的是整个数组,默认指向第一行的地址a[0]。
a[0],指向的是第一行,默认指向第一行第一个元素的地址a[0][0]。
a[0][0],指向第一行第一个元素的地址a[0][0],不需要默认就是。
因为a[0][0]在a[0] 里,a[0]在a里,虽然他们在内存里各自的存储空间长度不同,但是起点是一样且重合的。所以在昨天打印时会得到:
a = &a = *a = a[0] = &a[0] = &a[0][0] 的结果。
但是取值的时候切不可将他们认为他们可以一样使用:
因为*a等同于a[0],依然是一个地址。
*(&a)是取地址的地址的值,依然是一个地址。
&(*a)是取地址的值的地址,还是个地址。
所以要取数组第一个元素的正确方式应该是:
*(*a)或者*a[0]或者*a[0][0]
总的来说二维数组,要取值就必须指向具体地址。所谓具体,就是指向的内存区域大小刚好只够储存唯一个值,或者说精确到多维数组最高维数组里单个元素的地址。可以这么认为:
a+默认 = a[0], 所以*a取不到a[0][0]的值,因为它还是个地址。
a[0] + 默认 = &a[0][0] ,所以*a[0]可以取到a[0][0]的值,
一维数组:a[5] = {1,2,3,4,5};
int *p = a; (合法)
int *p = &a;(合法)
int *p = a[0];(合法)
int *p = &a[0];(合法)
二维数组:a[3][4] = {{1,2,3,4},{5,6,7,8},{11,22,33,44}}
int *p = a; (不合法)
int *p = &a;(不合法)
int *p = a[0];(合法)
int *p = &a[0];(不合法)
int *p = &a[0][0];(合法)
int (*p)[4] = a (合法) 代表指针指向的是一个列数为4的二维数组
上一篇有这样一个公式:*(*(a + i) + j) = a[i][j],等同于*(*(p + i) + j)
a只能参与+运算,和-运算。不能参与++和–运算,因为a的地址是个常量。但是p可以,这是它存在的一个很重要的意义。
另外注意这里的指针变量p,只有按int (*p)[4] = a这种格式定义才能实现跨行功能,其它合法格式定义的P都只能逐个移动下标。
用指向数组的指针作为函数参数
#include <stdio.h>int i = 0, j = 0;int a[10];int *p1 = &a[0];change(int a[10],int *p){ for(i = 0;i < 10; i++) { for(j = 1;j < 10;j++) { if(*(p+j) > *(p + j - 1)) { int t; t = *(p+j); *(p+j) = *(p + j - 1); *(p + j - 1) = t; } } }}void main(){ printf("\n\n以下是随机生成的数组:\n"); for(i = 0;i < 10;i++) { a[i] = rand()%100+1; printf("%d ",a[i]); } change(a,p1); printf("\n\n经过排序后:\n"); for(i = 0;i < 10;i++) { printf("%d ",a[i]); } getchar();}
函数指针
1,函数指针定义初始化
1)把函数考入到我们调用个main函数里面
2)挖掉函数名,把函数名改成*+函数指针标识符,其它部分原封不动。
就像这样:int(*p)(int a,int b)
2,把*p指一个函数地址。(函数名指向的就是函数存储区域的首地址 )
3,调用格式:p(实参1,实参2).
废话不多说,上代码:
输入两三个数,输出较大值或较小值# include<stdio.h>int i = 0,j = 0,k = 0;m = 0,n = 0,max = 0,min = 0;int m1(int a,int b,int c){ m = a > b ? a : b; max = m > c ? m : c; return max;}int m2(int a,int b,int c){ n = a < b ? a : b; min = n < c ? n : c; return min;}void main(){ int (*p1)(int a,int b,int c); //Windows下这两条必须放在函数第一行 int (*p2)(int a,int b,int c); //Windows下这两条必须放在函数第一行 printf("任意输入三位数字:\n"); scanf("\n%d\n%d\n%d",&i,&j,&k); getchar(); p1 = m1; //初始化 p2 = m2; //初始化 printf("\n最大值是: %d",p1(i,j,k)); //函数指针的调用 printf("\n最小值是: %d",p2(i,j,k)); //函数指针的调用 getchar();}
- 数组传参的特殊性,数组指针,函数指针
- 函数指针,函数指针数组,函数指针数组的指针
- 函数指针,函数指针数组,函数指针数组的指针
- 函数指针,函数指针数组,函数指针数组的指针
- 函数指针、函数指针数组,函数指针数组的指针
- 指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针
- 理解 指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针
- 指针数组,数组指针,函数指针,函数指针数组,指向函数指针数组的指针
- 指针数组 数组指针 函数指针 函数指针数组 函数指针数组的指针
- 学习:“指针数组”、“ 数组指针 ”、“函数指针”、“ 函数指针数组”、“指向函数指针数组的指针”
- 理解指针数组、数组指针、函数指针、函数指针数组、指向函数指针数组的指针
- 理解 指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针
- 指针数组,数组指针,函数指针,函数指针数组,指向函数指针数组的指针
- 数组指针、 指针数组、函数指针、函数指针数组和指向函数指针数组的指针
- 关于指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针
- 简述指针数组 数组指针 函数指针 函数指针数组和函数指针数组的指针
- 辨析指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针
- 理解 指针数组 数组指针 函数指针 函数指针数组 指向函数指针数组的指针
- 架构漫谈(三):如何做好架构之识别问题
- 动态规划算法求解硬币找零问题(Java)
- 数据结构实验之二叉树七:叶子问题
- 一些常用的第三方库
- 【杭电2602】01背包
- 数组传参的特殊性,数组指针,函数指针
- Apache Shiro学习(二)认证
- 二叉树前序、中序、后序遍历相互求法
- OFBiz中JOB的运行机制
- HTTP协议及其POST与GET操作差异
- size_t是什么
- 小红书Android客户端演进之路
- C# 冒泡排序实现
- poj---Relative Relatives