标签:
什么是指针?
指针是一类数据类型的统称.
这种类型的数据用来专门存储内存中的一块空间的编号,用于表示这一段内存.以实现通过内存地址(编号)完成各种运算.也就是一个指针指向一块内存空间,指针把这一块空间的第一个Byte的空间的地址存在指针的右值中.指针自己也是有内存空间和内存地址的.
数祖名也是个指针,而且是个常量指针. 该指针指向数组在内存中的那块空间,并把数组第一个字节的地址存在指针的右值中.该地址和数组第一个元素的首地址相同. 指针的类型有很多,其他在下面体现,这里就不一一举例了.
常见的两种和指针有关的操作符:
#1 * 定义指针的时候相当于类型说明符,说明接下来定义的变量是指针类型; 在使用指针变量时 *p 代表把指针变量p指向的内存空间的值去除;
int a, *p, p = a; *p = 5;
在定义一个指针时 int * p中的 * 并不是算术运算符乘, 像这样一词多义的情况,在C语言中还有很多. 在这里 * 是指针类型说明符, 说明p是一个指针, 这里的int 代表指针p指向的内存空间存放的数据是int 类型的.*p = 5, 这里的 * 又是另一个意思, 是一个间接引用运算符.它代表取出指针指向的空间, 在这里是把int类型数据5拷贝到指针p指向的内存空间中, 也就是把变量a的右值改成5.
#2 & 取指针运算符
之前学习scanf(“%d”, &a)函数时常用的”&”符号,其实就是求指针运算符,取得一个指针指向变量a的空间,&a把a的空间的手地址存放在&a的右值中.通过这个指针可以找到a的地址,从而把接受到的数据按照%d的格式存放在a的空间.
指针的优点:
a.为函数提供修改调用变量的灵活手段;
b.让函数有多个返回值
c.可以改善某些子程序的效率
在数据传递时,如果数据块较大(比如说数据缓冲区或比较大的结构),这时就可以使用指针 传递地址而不是实际数据,即提高传输速度,又节省大量内存。
d.为动态数据结构(如二叉树、链表)提供支持
如果一个指针指向另一个指针,则称这个指针为二级指针. 二级指针的右值存放的是一级指针的地址.
定义指针时, 变量名前有几个*就是几级指针.
<其他待补充...>
即指向一维数组的指针.
int a[5] = {1, 2, 3, 4, 5}; int *p =a;
指针变量p指向数组a的空间,a的首地址作为值存放在p的右值中.这是指针变量p可以代替数祖名使用,例如p[0], 相当于a[0].但由于p是变量,所以可以使用++ -- 等运算,但是数组名是常量,则不可以这样运算.
指向二维数组的指针.内容存放的是数组的行首地址.
int arr[3][5]; int (*p)[5] = arr;
二维数组指针是单个的变量. p + 1, 代表第二行的指针.
*注意: #1 *p左右的括号不可少, 如果少了括号则变成二维指针数组
#2 指定列宽[5]不可少, 这是要告诉编译器该数组指针指向的数组结构,其列宽是5.
即:数组的内容存放的是指针变量
int a, b, c;
int *p[3] = {&a, &b, &c};
当两个指针指向同一个数组, 两个指针想减的结果说明两个指针相隔了几个元素.p1 - p2 > 0 说明p1在高地址位, 相反则在低地址位. p1 - p2 == 0则说明两个指针指向了同一个元素.
两指针之间只有减法运算有意义,其他运算是没有意义的.
如前面所说,数组名也是个指针,所以通过数组名也可以访问数组中的每个成员.
int a[3][5];
a + i : 可以代表行的首地址, 也就是行指针
a[0] + j : a[0] + j可以代表列指针
(*(a + i) + j) : 可以代表任意一个元素的地址,所以
*(*(a + i) + j): 可以取出任意一个元素的值
指向字符串的指针.
1. 定义方法:char *变量名 = ”字符串内容“;// “字符串内容”是常量,保存在内存中的常量区
作用:用来保存一个字符串,保存了字符串的首地址
2. 字符串指针不能从键盘接收一个字符串,但是可以通过malloc()先申请一定长度的内存空间,用来接收键盘输入的字符串。
#1 字符数组
把字符串通过数组保存到栈中,内容是可读可写的,也就是说可以改变字符数组的内容
#2 二维字符串数组
#3 字符串指针:
指向字符串常量的首地址,字符串常量是只读的,不可以更改其内容。但是字符串指针可以重新指向其他字符串地址。
#4 char类型指针数组
char *p[3] = {"Hello", "ZJL", "Hello"};
数组每个元素都指向一个字符串.
返回值为指针的函数称为指针函数.
定义:
类型说明符 *函数名(形参列表){
函数体;
}
函数名前加*说明返回的是指针,类型说明符说明返回的指针指向的空间内元素的类型.
一个函数总是占用一段连续的内存空间,函数名就是该函数空间的首地址.我们把这种指向函数的指针变量称为”函数指针”;
函数指针变量的定义:
返回值类型 (*变量名)(函数的参数);//可以省略形参名,但不能省略形参类型
注意:
1)函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可 使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。
2)函数调用中"(*指针变量名)"的两边的括号不可少,其中的*不应该理解为求值运算,在此处它 只是一种表示符号
定义指针时,没有初始化该指针. 又或者指针指向目标丢失(例如malloc等函数生成的内存空间被free后),这样的指针叫野指针.
定义指针变量的同时如果没有指向一个确定的目标,最好初始化为NULL,用完指针后也将指针变量设置为NULL.
内存泄漏:
int *p = (int *)malloc(16);p在棧中, malloc(16)在堆中
解决方法:p释放前,先释放堆中的malloc(16)申请的空间
free函数使用:先导入库文件
free(p);//p要释放的空间的首地址,free代表p指向的那块空间可以被重新利用
p = NULL;//把释放空间后的指针指向NULL,避免p还指向之前的内存空间
1. 常见的内存分配的函数
malloc calloc realloc 在堆中分配空间
###malloc
void *malloc(unsigned size),包含在库函数sodlib.h中,作用是在内存的队区分配一个大小为size连续的内存空间,如果分配成功,函数返回新分配内存的首地址,否则,返回NULL.注意:鉴于上述这点,一般在写程序需要判断分配内存是否成功
注意:
malloc申请的空间,如果该空间不初始化(赋值),则空间内容是不确定的.
memset(p, ‘A’, 16);这个函数可以给malloc申请的空间初始化,内容全部为’A’,其中p为接收malloc申请空间的指针,16为空间大小.
###calloc
clloc(块数,每块的长度),分配指定块数的连续的内存空间.分配成功则返回空间首地址,否则返回NULL.
注意:
calloc分配内存空间成功后,会自动初始化分配的内存空间,初始化为0.
###realloc
realloc可以给已经存在的空间重新分配大小,但地址可能会改变.之前空间的数据不会丢失,会被拷贝到新的空间.所以在使用该函数时,需要把返回值重新赋值给之前的指针.
标签:
原文地址:http://www.cnblogs.com/siyingcheng/p/4617572.html