指针
指针的重要性:
表示一些复杂的数据结构
快速地传递数据,减少内存的耗用【重点】
使函数返回一个以上的值【重点】
能够直接访问硬件
能够方便的处理字符串
是立即面向对象语言中引用的基础
总结:指针是c语言的灵魂
指针的定义:
地址:
内存单元的编号
从零开始的非负整数
范围:4G【0到4G-1】
指针:
1、指针就是地址,地址就是指针
例如:int *p = a[5];
p是指针,&a[0]地址,地址等价于指针
所以可以这样说:
p等价于a等价于&a[0]
p+i等价于a+i等价于&a[i]
2、指针变量就是存放内存单元编号(说白了就是地址)的变 量,或者说指针变量就是存放地址的变量。
3、指针(*p)和指针变量§是两个不同的概念但是要注意的是:我们通常叙述时会把指针变量简称为指 针,实际上它们的含义并不一样。
4、指针的本质就是一个操作受限的非负整数。
指针的分类
1、基本类型指针【重点】
int *p; //p是变量的名字,int *表示p变量存放的是int*类型变量的地址。
//int *p;不表示定义了一个名字叫做*p的变量
//int *p;应该这样理解:p是变量名,p变量的 数据类型是int *类型,所谓int *类型 实际就是存放int变量地址的类型。
int i = 3;
int j;
p = &i;
1、p保存了i的地址,因此p指向i;
2、p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值也不会影响p的值
3、如果一个指针变量只想某个普通变量,则*指针变量 就完全等价于 普通变量*p 就完全等价于 a[0]。
例子:
如果p是某个指针变量,并且 p 存放了普通变量 i 的地址(即上面的int * p; int i; p = &i;)
则p 指向普通变量 i
*p 就完全等同于 i
后者说:在所有出现*p的地方都可以替换成i
在所有出现i的地方都可以替换成*p
*p最准确的解释是:*p表示的是以p的 内容为地址的变量。
j = *p; // 等价于 j = i;
printf(“i = %d, j = %d\n”, i, j);
附录:
*的三种含义
1、乘法符号
2、定义指针变量
int *p;
//定义了一个名叫p的变量,int * 表示p只能存放int类型变量的地址
3、指针运算符
(1)该运算符放在已经定义好的指针变量的前面。
(2)如果p是一个已经定义好的指针变量则*p表示以 p的内容为地址的变量。
如何通过被调函数修改主调函数变量的值:
1、实参必须为该普通变量的地址。
2、形参必须为指针变量。
3、在被调含糊中通过。
*形参名 = …
的方式就可以修改主调函数相关变量的值。
指针和数组
指针和一维数组
一维数组名(比如a[4]的a就是数组名)
一维数组名是一个指针常量(int *p;int a[10];a等价于p;*(p+i)等价于a[i]也等价于p[i];)
它存放的是一维数组第一个元素的地址。
下标和指针的关系
如果p是一个指针变量,则
p[i]永远等价于*(p+i)
确定一个一维数组需要几个参数【如果一个函数要处理一个一维数组,则需要接收该数组的那些信息】
需要两个参数:
(1)数组的第一个元素的地址a。
(2)数组的长度。
指针变量的运算:
指针变量不能相加、乘、除
如果两个指针变量指向的是同一块连续空间的不同储存单元,则这两个指针变量才可以相减。
例如:
int a[5] = {1,2,3,4,5};
int * p;
int * q;
p = &a[1];
q = &a[4];
printf(“%d\n”, q-p);
输出值为3. //p和q所指向的单元相隔q-p个单元
p+i等价于p+i*(p指向的变量所占的字节数)
一个指针变量到底占几个字节【非重点】
预备知识:
sizeof(数据类型)
功能:返回值就是该数据类型所占的字节数
例子:sizeof(int) = 4 sizeof(char) = 1
sizeof(double) = 8
sizeof(变量名)
功能:返回值是该变量所占的字节数
假设p指向char类型变量(1个字节)
假设q指向int类型变量(4个字节)
假设r指向double类型变量(8个字节)
请问:p、q、r、本身所占的字节数是否一样?
答案:p、q、r本身所占字节数是一样的
总结:
一个指针变量,无论他指向的变量占几个字 节该指针变量本身只占八个字节(64位操作 系统下,32位占4个字节)
一个变量的地址就是用该变量首字节的地址来表示
如何用被调函数修改主调函数中数组元素的值:
/*
被调函数如何修改主调函数中数组元素的值。也可以用来作为数组元素的排序、查找。
*/
#include<stdio.h>
void g(int *p,int j)//接收数组的首地址和长度
{
int i;
for(i=0; i<j; i++)
{
p[i] = 100;//p接收了数组a的地址,那么p = a;*(p+i) 等价于a[i]也等价于p[i]也等价于*(a+i)也等价于i[a];
}
return 0;
}
int main()
{
int a[5]={1,2,3,4,5};
int i;
g(a,5);//a等价于&a[0],&a[0]是整形指针变量,向被调函数发 送数组的首地址a和数组的长度5;
for(i=0; i<5; i++)
{
printf("%d\n",*(a+i));
}
return 0;
}
/*
输出结果
100
100
100
100
100
*/
多级指针
用法:
#include<stdio.h>
void f(int **q)
{
**q = 100;//q是int **类型, 所谓int **类型就是指q只能存放int *类型变量的地址
}
int main()
{
int i = 10;
int *p = &i;
int **q = &p;
int ***r = &q;
f(&p);
printf("%d\n",*p);
//*q = &p; error
//**q = &i;error
printf("%d\n",**q);
printf("%d\n",***r);
return 0;
}
输出结果:
100
100
100