运算符&
取地址符,用来取操作数的地址
是scanf("%d", &i);里的&
获取变量的地址,操作数必须是变量
int i; printf("%x", &i);
地址的大小是否与int相同取决于编译器
int i; printf("%p", &i);
指针
就是保存地址的变量
int i; 普通变量
int* p = &i; 将 i 的地址赋值给p;
int* p,q; q是普通变量,p是指针
int *p,q; q是普通变量,p是指针 星号位置不影响
指针变量
变量的值是内存的地址
普通变量的值是实际的值
指针变量的值是具有实际值的变量的地址
作为参数的指针
void f(int *p);
在被调用的时候得到了某个变量的地址:
int i=0;f(&i);
在函数里面可以通过这个指针访问外面的这个 i ;
访问那个地址上的变量*
*是一个单目运算符,用来访问指针的值所表示的地址上的变量
可以做右值也可以做左值
int k = *p;
*p = k+1;
函数参数表中的数组实际上是指针
sizeof(a) == sizeof(int*)
可以用数组的运算符[]进行运算
以下四种函数原型是等价的
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; 无需用&取a的地址
但是数组的单元表达的是变量,需要用&取地址
a == &a[0]
[]运算符可以对数组做,也可以对指针做:
p[0] 等价于 a[0]
*运算符可以对指针做,也可以对数组做:
*a = 25;
数组变量是const的指针,所以不能被赋值
int a[] 等价于 int * const a
指针应用场景
1.交换两个变量的值
2.函数返回多个值,某些值就只能通过指针返回
2.1传入的参数实际上是需要保护带回的结果的变量
2.2函数返回运算的状态,结果通过指针返回
3.常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:0 或 -1
指针是const时
int *const q = &i; //q是const
*q = 26; // OK
q++; //ERROR
所指是const时
表示不能通过这个指针去修改那个变量(并不能使那个变量成为const)
const int *p = &i; (*p)是const的
*p = 26; //ERROR
i = 26; //OK
p = &j; //OK
下列四个定义的意思
int i; 普通变量
const int* p1 = &i; *p1是 const
int const* p2 = &i; *p2是 const
int *const p3 = &i; p3是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!
当要传递的参数的类型比地址大的时候,这是常用的手段
指针加一的情况
给一个指针加 1 表示要让指针指向下一个变量
int a[10]; int *p = a[0]; *(p+1) ==> a[1]
如果指针不是指向一片连续分配的空间,如数组,则这种运算无意义
指针运算
这些算术运算可以对指针做
给指针加、减一个整数(+,+=,-,-=)
递增递减(++,–)
指针比较
<, <=, ==, >, >=, != 都可以对指针做
比较它们在内存中的地址
数组中的单元地址肯定是线性递增的
指针的类型
无论指向什么类型,所以的指针的大小都是一样的,因为都是地址
但是指向不同类型的指针是不能直接互相赋值的
这是为了避免用错指针
指针的用处
需要传入较大的数据做参数
传入数组后对数组做操作
函数返回不止一个结果
需要用函数来修改不止一个变量
动态申请的内存…