使用指针的几个方面:
- 需要传入较大的数据时用作参数;
- 传入数组后对数组做操作;
- 函数返回不止一个结果;
- 需要用函数来修改不止一个变量;
- 动态申请的内存。
int i,j;
const int *p = &i;
*p = 26;//error
i = 26;//ok
p = &j;//ok
所指是const,即指向常量的指针,仅仅要求不能通过该指针改变对象的值,表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const,p和i是可以改变的)。
const int* p1 = &i;//所指是const,即指向常量的指针
int const* p2 = &i;//同上形式
int *const p3 = &i;//指针是const,即常量指针
判断哪个被const了的标志是const在*的前面还是后面。如果const在*后面,表示指针不能被修改。
常量指针必须初始化,而且一旦初始化完成,则它的值(也就是存放在指针中的那个地址)就不能再改变。
void f(const int* x);
int a=15;
f(&a);//ok
const int b=a;
f(&b);//ok
b=a+1;//error
总是可以将一个非const常量转化成const。
当要传递的参数类型比地址大的时候,这是常用的手段:既能用比较少的字节数传递值给参数,又能避免函数对外面的变量的修改。
const int a[]={1,2,3,4,5};
数组变量已经是const指针了,这里的const表明数组的每个单元都是const int类型,所以必须通过初始化进行赋值。
int sum(const int a[], int length);
传数组时函数内部可以修改数组的值,为了保护数组不被函数破坏,可以设置参数为const。
int a[10];
int *p=a;
//*(p+i)-->a[i]
a[] = {5, 15, 34, 54, 14, 2, 52, 72};
int *p = &a[5];
printf("p[-2]=%d\n",p[-2]);
*(p+i) == a[i] 也等效于 p[i] == a[i],输出结果为 p[-2]=54。
给指针+i表示要让指针指向下一个变量,如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义。
int *p = &i;
void *q= (void *)p;
这并没有改变p所指的变量类型,而是让q用不同的眼光通过p看到它所指的变量。q不再当i是int,而是认为i就是个void。
int *p;
p = (int *)malloc(sizeof(int));
p++;
free(p);
会报错,free的p值必须是原来申请空间的首地址。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *a=0;
double *b=0;
a = (int *)malloc(sizeof(int));
b = (double *)malloc(sizeof(double));
printf("the address is a=%p b=%p\n",a,b);
printf("the length of a and b is a=%d b=%d\n",sizeof(*a),sizeof(*b));
printf("the length of b-a is %d\n",((int*)b-a)*sizeof(int));//强制类型转换将double*类型转换成int*类型
printf("the address of (malloc(0)) =%p\n",malloc(0));
free(a);
free(b);
return 0;
}
由 b-a=64 可知相邻两次malloc得到的空间地址并不连续。
得到空间的实际大小比自己要求的空间大小大。
当malloc一个零长度,仍旧会得到一个地址空间。
- 数组变量是const指针,所以两个数组变量之间不能被赋值:int a[] <---->int * const a。
- 在指针在初始化之前,不能够使用*p去访问它的元素。否则可能会对非法内存空间进行修改。好习惯是申明指针的时候就初始化,如果不确定指向什么则先初始化为0。
- 指针在输出地址的时候,使用%d则是输出地址的整数结果,%p则是输出16进制结果。