指针
指针变量
普通变量存储的是实际的值
指针变量的值是具有实际值的变量地址
取地址(&)
int *p 其中的p称为指针
并且是*p 为一个整体 而不是int *
&i (i为一个变量)代表i的地址,而不是i的实际值
p(指针)可以存储这些变量的地址
#include <stdio.h>
void a(int*p);
int main()
{
int i=2;
printf("%p\n",&i);
a(&i);
return 0;
}
void a(int*p)
{
printf("%p",p);
}
如图
二者结果输出都为同样的值,说明了p存储的是i的地址
访问地址上的变量
i的地址通过**&i传递到p**,而p可以通过p的方式去访问到i*的实际量,同时也可以修改
p可以位于左值也可以位于右值*
左值命名原因
*p位于赋值号左边的时候,它不是一个变量,而是值,是一个特殊的值
#include <stdio.h>
void a(int* p);
int main()
{
int i = 2;
printf("%d\n", i);
a(&i);
printf("%d\n", i);
return 0;
}
void a(int* p)
{
*p = 4;
}
此时输出第一个值是i的初始值2,后一个值输出的是通过p修改的i*变量的实际值4
指针的使用场景
1.函数结果不止一个,且需要函数返回多个值,通过指针返回
例如之前通过自定义函数无法实现的数值交换
#include <stdio.h>
void swap(int*a,int*b);
int main()
{
int a=4,b=3;
swap(&a,&b);
printf("a%&d,b=%d",a,b);
return 0;
}
void swap(int*a,int*b)
{
int c;
c=*a;
*a=*b;
*b=c;
}
2.函数返回运算状态,结果通过指针返回
即表示指针返回特殊的值来表示出错(常用的是-1或0)
如果任何数值都是在有效范围内,就必须分开返回
3.传入数组对数组操作
4.传入较大数据时用作参数
数组变量
数组变量是一种特殊的指针,本身表达地址,所以无需用&取地址,但是数组的单元(是一个变量)需要,比如&a[1]
int *a和 int a[] 是等价的
函数参数表中的数组实际上是指针,但是可以用数组的运算符运算
- []可以作用在指针上
比如 p[0]==a[0]
- *也可以作用在数组上
*a==a[0]
ps:数组变量无法进行赋值 (int a[]=b是不行的,int * p=b是可行的)
因为int a[] 其实是 int *const a ,是一个常量指针
指针与常量
指针可以是const ,或者指针所指的也可以是const
比如 int*const p 代表的是a这个指针是一个const,p里面存储的地址无法被改变
int const*p 代表的是 *p是一个const, *a无法改变a所指向的值
(const int* p 和 int const *p 是一样,只要const在 *p前面,就是const的为 *p)
作用:用于通过指针传递的值,而又不会被指针修改
const数组
const int a[]=[1,2,…]
代表的是数组a中的每一个int都是const,只能通过初始化赋值
指针的运算
指针也可以进行运算
比如 指针加1
#include <stdio.h>
int main()
{
int a[] = { 1,2,3 };
char b[] = { 1,2,3 };
char* p = b;
int* t = a;
printf("p=%p\n", p);
printf("p+1=%p\n",p+1);
printf("t=%p\n", t);
printf("t+1=%p\n", t + 1);
return 0;
}
结果如图
说明了指针+1的实际操作是将指针移到下一个变量去,char类型的占1字节,所以指针移动只加了1,而int占4字节,指针加1结果加了4.
*p同时也能进行运算;
int a[]={0,1,2,3,4};
int *p=a;//其实代表*p=a[0]
//*(p+1)其实等于a[1]
所以*p之间的加减其实代表数组的元素移动(前提指针指向的是连续的分配的空间)
指针计算(+ , - ,+= , -= ,++ ,–) 不能乘除
两个指针也能进行相减
#include <stdio.h>
int main()
{
int a[] = { 1,2,3 };
int* p = &a[0];
int* p1 = &a[2];
printf("p1=%p\n", p1);
printf("p=%p\n", p);
printf("p1-p=%d\n", p1 - p);
return 0;
}
结果值就是两个指针地址所减的值,然后除以所占字节数(int是4字节),然后等于8
*p++ (取出p的数据,然后再移向下一个)
p++的优先级高于 *,所以不用括号p++
0地址:不能随便碰的地址,所以指针不应该具有0地址(但是都有),所以可以用0地址来表示特殊事情,比如返回0地址告诉你结果(出错或成功)
表示:NULL(有的编译器0地址不适用)
指针比较(地址大小的比较<–运用条件运算符)
指针的类型(不同类型指针不能互相赋值,也不能直接赋值)
int *p;
char *q;
p=q;//这是不被允许的
指针类型转换
int*p=&i;
void*q=(void *)p;
没改变p指向变量的类型,但是改变了后面的 用void的眼光去通过p看变量类型
所以通过(变量类型*)可以去强行转换指针类型