本帖最后由 双元No.1 于 2016-9-5 01:00 编辑
指针是C语言中非常重要的数据类型,如果你说C语言中除了指针,其他你都学得很好,那你干脆说没学过C语言。究竟什么是指针呢?我们先来看一个概念。
1. 回想一下,之前我们是如何更改某个变量的值?
我们之前是通过变量名来直接引用变量,然后进行赋值:
2. 看上去是很简单,其实程序内部是怎么操作的呢?
其实,程序对变量的读写操作,实际上是对变量所在的存储空间进行写入或取出数据。就上面的代码而言,系统会自动将变量名a转换为变量的存储地址,根据地址找到变量a的存储空间,然后再将数据10以2进制的形式放入变量a的存储空间中。
3. 通过变量名引用变量,由系统自动完成变量名和其存储地址之间的转换,称为变量的"直接引用"方式
1.我们已经知道,"直接引用"是直接通过变量名来读写变量
2.C语言中还有一种"间接引用"的方式(以变量a为例):首先将变量a的地址存放在另一个变量中,比如存放在变量p中,然后通过变量p来间接引用变量a,间接读写变量a的值。这就是"间接引用"。
如果程序通过"间接引用"的方式来修改a的值,可以这样做:先根据 变量名p 获取 变量p 的地址0x7fff5fbff780,取出变量p中存储的内容0x7fff5fbff78f,也就是变量a的地址,再根据变量a的地址0x7fff5fbff78f找到a的存储空间,然后修改里面的数据。
3.总结一句:用来存放变量地址的变量,就称为"指针变量"。在上面的情况下,变量p就是个"指针变量",我们可以说指针变量p指向变量a。
严格上来讲,指针具有两层含义:一是指一种保存地址的变量,二是指一种数据类型.
用于存储某一个地址,从而可以通过地址直接对该地址内存空间中的数据进行操作.
[C] 纯文本查看 复制代码
// 定义int类型的变量a
int a = 10;
// 定义一个指针变量p
int *p;
// 将变量a的地址赋值给指针变量p,所以指针变量p指向变量a
p = &a;
[C] 纯文本查看 复制代码 // 定义int类型的变量a
int a = 10;
// 定义一个指针变量p
// 并将变量a的地址赋值给指针变量p,所以指针变量p指向变量a
int *p = &a;
[C] 纯文本查看 复制代码 int *p;
p = 10;//这是错误的
当需要存储地址,以便于操作该地址及地址对应的内存数据的时候
6.有什么特点?(注:一下的p表示一个指针变量名)
- 指针本身也有地址:指针定义之后,自身地址不变,但里面存的地址可以变化.
- &p表示指针自身地址,而p表示指针存的地址,*p表示指针所存地址的内存空间.
- 指针不初始化赋值不要使用.未赋值前地址是随机的,未赋值不可以用*p.
- *修饰什么,就表示是什么的指针.判断原则:先确定变量的类型.(根据符号优先级)
- 指针是什么类型的,就应该存什么类型的地址.否则*p取对应内存空间的值会出错.
表示一个数组,用来存指针的数组就叫做指针数组.数组里面的元素都是指针
[C] 纯文本查看 复制代码 int *p[2];//表示定义一个可以存放三个int指针的数组.
//赋值:
int a1 = 1,a2 = 2,a3 = 3;
int *p[3] = {&a1,&a2,&a3};
//取值:
int *a = p[0];
表示一个指针,而这个指针类型是数组
[AppleScript] 纯文本查看 复制代码
int arr[3] = {1,2,3};
int *p = arr;
补充:
什么是数组元素的指针?
表示一个指针,而这个指针存的是一个元素的地址.
[AppleScript] 纯文本查看 复制代码 int arr[2] = {1,2};
int *p = &arr[0];
- 数组名表示第一个元素的地址,&数组名表示整个数组的地址,二者值相同,但意义不同.
- 指针可以运算,但仅限于加减运算.运算的实质就是地址运算.即地址的移动.
- 地址(+1)向高位移动,而(-1)向低位移动.不同指针类型移动一位(+1或-1)的字节数不同.
[C] 纯文本查看 复制代码 int arr[3] = {1,2,3};
int *p = arr;
int a = *p;
//a = *(p+1);//等效于:int *p1 = &arr[1];a = *p1
- 实际移动的字节数看指针类型,类型占多少个字节,一位就移动多少个字节.
是一个数组,里面的每一个子数组存的元素的类型是指针.
例如:
[C] 纯文本查看 复制代码 int a = 0,b = 1,c = 2,d = 3,e = 4,f = 5;//定义int型变量
//获取所以变量的指针
int *pa = &a;
int *pb = &b;
int *pc = &c;
int *pd = &d;
int *pe = &e;
int *pf = &f;
//定义这个二维指针数组
int *p[2][3] = {{pa,pb,pc},{pd,pe,pf}};
是一个指针,只是指针类型是二维数组.
例如:
[C] 纯文本查看 复制代码 int arr[2][3] = {{1,2,3},{4,5,6}}//这是一个二维数组
int (*p)[3] = arr;//这就是一个二维数组指针.
[C] 纯文本查看 复制代码 //一,怎么表示一个字符串?
char arr[] = "heima";
//二,怎么用指针表示一个字符串?
char *p = "hiema";
//三,怎么表示一个字符串数组?
char arrs[2][8] = {"itcast","heima"};
//四,怎么用指针表示一个字符串数组?
char *arrs[2] = {"itcast","heima"};
//五,注意事项
//1.指针定义的字符串是常量,不能被改变,而字符数组定义的是变量,可以被改变.
//2.指针定义一个字符串,指针存的实际是在常量区的那个字符串的首字符的地址
首先是函数.这个函数的返回值类型是指针;
定义语法: 类型 * 函数名(参数){return 指针类型;}
例如:
[C] 纯文本查看 复制代码 int *add(int *a){return &a;} //表示定义一个返回值是int 指针类型的add函数.
首先是指针.函数也会在内存中开辟一块空间.函数指针即这块空间的地址.
定义: 函数返回值类型 (*指针名)(参数类型);
赋值: 指针名 = 函数名;
例如:
[C] 纯文本查看 复制代码 //先定义函数
int add(int a){
//..........
return a;
}
int (*p)(int) = add;
使用:指针名(实参);
例如:
[C] 纯文本查看 复制代码 p(3);//等效于add(3);
是指针,只不过是指针类型是结构体类型.
用于存储结构体的地址,并操作地址对应的结构体空间里的数据
定义及初始化赋值: struct 结构体类型 *指针名 = &结构体变量
例如:
[C] 纯文本查看 复制代码 struct Person{
char *name;
int age;
};
struct Person per = {"itheima",2};
struct Person *p = &per;
取值语法:(*指针名).结构体元素名; 指针名 -> 结构体元素名;(结构体独有的用法)
赋值:(*指针名).结构体元素名 = 新值; 指针名 -> 结构体元素名 = 新值;
例如:
[C] 纯文本查看 复制代码 (*p).name ; (*p).age;或者 p->name;p->age;
当需要使用指针操作结构体时.
1.指针移到对结构体本身没有意义.结构体名并不包含第一个元素的地址.
|
|