-
取地址运算
运算符&:获得变量的地址,它的操作数必须是变量。
地址的大小是否与int相同取决于编译器。
int i; printf("%p",&i);
注:&不能取的地址,&不能对没有地址的东西取地址。如:&(a+b)、&(a++)
-
指针
指针就是保存地址的变量。
指针变量:变量的值是内存的地址。
作为参数的指针:void f(int *p); 在被调用的时候得到了某个变量的地址。
-
访问某个地址上的变量
使用*运算符,*是一个单目运算符,用来访问指针的值所表示的地址上的变量。
可以做左值也可以做右值。
如:int k = *p; *p = k+1;
左值之所以叫左值是因为出现在赋值号左边的不是变量,而是值。
-
指针的运算符&*
对于*&:*&yptr—>得到指针所指那个地址上的变量。
对于&*:&*yptr—>&(*yptr)—>&(y)—>得到y的地址,也就是yptr—>yptr
-
指针应用场景
交换两个变量的值:
void swap(int *pa, int *pb)
{
int t = *pa;
*pa = *pb;
*pb = t;
}
函数返回多个值,某些值就只能通过指针返回。
-
指针常见错误
定义了指针变量,还没有指向任何变量,就开始使用指针。
-
指针和数组
函数参数表中的数组实际上是指针。但是指针可以用数组的运算符[]进行运算。
以下函数原型是等价的:
int sum(int *ar, int n);
int sum(int *, int);
int sum(int ar[], int n);
int sum(int [], int);
数组变量是特殊的指针,数组变量本身表达地址,所以int a[10]; int *p = a;不需要使用&取地址。
[ ]运算符可以对数组做,也可以对指针做。
*运算符可以对指针做,也可以对数组做。
数组变量是const的指针,所以不能被赋值。
-
指针与const
指针和值都可以是const
如果指针是const,表示一旦得到了某个变量的地址,就不能再指向其他变量了,
int *const q = &i; //表示q是const
*q = 26是正确的赋值
q++则是错误的。
指针所指的是const,表示不能通过这个指针去修改那个变量,(并不能使得那个变量成为const)
const int*p = &i;
*p = 24 //是错误的,因为(*p)是const
i = 26 //是正确的
p = &j //正确
看一下下面这些是啥意思?
int i;
const int* p1 = &i;
int const* p2 = &i;
int *const p3 = &i;
//判断哪个被const了的标志是const在*的前面还是后面,const在*后面则表示指针是const
-
const数组
const int a[] = {1, 2, 3, 4, 5, 6};
这里的const表示数组的每个单元都是const int,所以必须通过初始化进行赋值。
保护数组值,因为把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值。
为了保护数组不被函数破坏,可以设置参数为const。
int sum(const int a[], int length);
-
指针的运算
给一个指针加1表示要让指针指向下一个变量。
如果指针不是指向一片连续的分配的空间,如数组,则这种运算没有意义。
-
*p++
取出p所指的那个数据来,完事之后顺便把p移到下一个位置去。
*的优先级虽然高,但是没有++高。
指针的比较:比较的是它们在内存中的地址大小。数组中的单元的地址肯定是线性递增的。
-
0地址
内存中是有0地址的,但是0地址通常是不能随便碰的地址。
所以指针不应该具有0值。
NULL是一个预定定义的符号,表示0地址。注意有的编译器不愿意你用0来表示0地址。
指针的类型:指向不同类型的指针是不能直接互相赋值的。
-
指针的类型转换
void*表示不知道指向什么东西的指针,指针也可以转换类型。
-
动态内存分配
int *a = (int *)malloc(n*sizeof(int));
malloc:#include <stdlib.h>
void * malloc(size_t size);
向malloc申请的空间的大小是以字节为单位的。
返回的结果是void*,需要类型转换为自己需要的类型。
如果申请失败则返回0,或者叫做NULL。
free():把申请得来的空间还给系统,申请的空间最终都要还,只能还申请来的空间的首地址。
整理自MOOC