指针
一、指针的简单用法:
二、指针的重要性:
1、表示一些复杂的数据结构
2、快速的传递数据
3、使函数返回一个以上的值
4、能直接访问硬件
5、能够方便的处理字符串
6、是理解面向对象语言中引用的基础
反正就是很重要!
指针的分类:
1、基本类型指针
2、指针和数组
3、指针和函数
4、指针和结构体
5、多级指针
三、指针的定义:
地址:
内存单元的编号
从零开始的非负整数
范围:4G【0——4G-1】
指针:
指针就是地址,地址就是指针,指针变量是存放地址的变量。
四、基本类型指针:
如下:
#include <stdio.h>
int main(void)
{ int * p;//p是变量的名字,int *表示p变量存放的是int类型变量的地址
int i=3;
p=&i;
/* 1、p保存了i的地址,因此p指向i
2、p不是i,i也不是p,也就是说修改p的值不影响i的值,修改i的值也不影响p的值
3、如果一个指针变量指向了某个普通变量,则
*指针变量就完全等同于普通变量,或者说所有出现的i都可以用*p替代,所有出现*p的地方都可以用i替换
*p就是以p的内容为地址的变量
*/
return 0;
}
经典指针程序——互换两个数的值、
代码如下:
#include <stdio.h>
void hh(int * p,int * q)
{ int t;
t=*p;
*p=*q;
*q=t;
return;
}
int main(void)
{ int a=3;
int b=5;
hh(&a,&b);
printf("a=%d b=%d\n",a,b);
return 0;
}
其中注意定义函数中是用*q *p和t互换,q,p是指针,属于地址;
如何通过被调函数来改变主调函数的值:
1、实参必须为该普通函数的地址
2、形参必须为指针变量
3、在被调函数中通过
*形参名=.....
的方式就可以修改主调函数相关变量的值
五、形参与实参:
形参和实参永远是不同的!
六、指针和数组:
1、指针和一维数组:
一维数组名
一维数组名是一个指针常量,它存放的是一维数组第一个元素的地址
如图:
2、下标与指针的关系:
如果p是个指针变量,则p[i]永远等价于*(p+i)
3、界定一个一维数组需要两个参数的原因:
运行如下代码可知
#include <stdio.h>
void f(int *arr,int len)
{ int i;
for(i=0;i<len;++i)
printf("%d ",*(arr+i));
}
int main(void)
{ int a[5]={1,2,3};
int b[100]={1,2,3,1,2,2};
f(a,2);
f(b,100);
return 0;
}
界定一个一维数组需要知道数组名和长度
4、指针变量的运算:
指针变量不能相加 不能相乘 也不能相除
如果两个指针变量指向的是同一块连续空间中的不同储存单元,
则这两个指针变量才能相减
5、一个指针变量到底占多少个字节?
一个指针变量,无论它指向的变量占几个字节,该指针变量本身只占四个字节。
七、动态内存分配:
1、 传统数组的缺点:
1、数组长度必须事先制定,且只能是常整数,不能是变量。
例子:
int a[5]; //ok
int len =5; int a[len]; //error
2、传统形式定义的数组,该数组的内存无法手动释放。
也就是说,在一个函数运行期间,系统为该函数的数组分配的空间会一直存在
3、数组的长度一旦定义,其长度在函数运行过程中就不能被改变
4、A函数定义的数组,在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,
A函数中的数组将不能被其他函数使用
2、为什么需要分配动态内存?
动态内存能够解决传统数组的缺陷
3、动态内存分配举例——动态数组的构造
malloc函数的使用:
a、要使用malloc函数,必须添加malloc.h这个头文件
b、malloc函数只有一个形参,并且形参是整形
例如以下代码
#include <stdio.h>
#include <malloc.h>
void f(int* q)
{
*q=200;
}
int main(void)
{ int* p=(int*)malloc(sizeof(int));
*p=10;
printf("%d\n",*p);
f(p);
printf("%d\n",*p);
return 0;
}
动态一维数组的构造:
代码如下:
#include <stdio.h>
#include <malloc.h>
int main(void)
{ int* arr;
int len;
int i;
printf("输入你想输入元素的个数");
scanf("%d",&len);
arr=(int*)malloc(4*len);
for(i=0;i<len;++i)
scanf("%d",&arr[i]);
printf("数组元素为:\n");
for(i=0;i<len;++i)
printf("%d\n",*(arr+i));
return 0;
}
此代码能够很好的体现出动态内存分配
4、动态内存与静态内存的比较
静态内存是系统自动分配,由系统自动释放
静态内存是在栈分配
动态内存是由程序员手动分配,手动释放
动态内存是在堆分配
八、多级指针:
静态变量不能跨函数使用详情
此代码
#include <stdio.h>
void f(int** q)
{ int i=10;
*q=&i;
}
int main(void)
{ int* p;
f(&p);
printf("%d\n",*q);
return 0;
}
在现在的编译器中运行报错
动态函数跨函数使用详情:
代码如下
#include <stdio.h>
#include <malloc.h>
void f(int** q)
{
*q=(int*)malloc(sizeof(int));
**q=5;
}
int main(void)
{ int* p;
f(&p);
printf("%d\n",*p);
return 0;
}
九、课后作业:
1、88 44 00 22
2、4个
3、ref地址是8的储存地址;ref+1是ref指向的地址之后的第一个地址;ref不能自增
4、 12 16;12 14;
5、 12 16;12 14;