指针理解的2个要点:
我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢?
准确的说:有的。
我们来讨论
当有这样的代码:
int num=0;
int*p=#
上述的代码就是把num的地址赋给一个整型p的指针变量。
但是什么是内存地址,我画一个图大家仔细的理解以下即可:
要将&num(num的地址)保存到p中,我们知道p就是一个指针变量,那它的类型是怎样的呢?
我们给指针变量相应的类型。
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
这里可以看到,指针的定义方式是: type + * 。
其实:
char* 类型的指针是为了存放 char 类型变量的地址。
short* 类型的指针是为了存放 short 类型变量的地址。
int* 类型的指针是为了存放 int 类型变量的地址。
总结:
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字。
接下来我们看一个例子,大家就知道怎么回事了。
//演示实例
#include
int main()
{
int n = 0x11223344;
char *pc = (char *)&n;
int *pi = &n;
*pc = 0; //重点在调试的过程中观察内存的变化。
*pi = 0; //重点在调试的过程中观察内存的变化。
return 0; }
我画一个示意图,大家参考一下
指针±整数
//指针相加
int main() {
double arr[5] = { 0 };
double* p = arr;
int i = 0;
for (i=0;i<5;i++)
{
printf("%lf ",*(p+i));
}
return 0;
}
// //两个指针相减的前提是:指针指向的同一块连续的空间
int main()
{
int arr[10] = {0};
printf("%d\n", &arr[9] - &arr[0]);
printf("%d\n", &arr[0] - &arr[9]);
int a = 10;
char c = 'w';
printf("%d\n", &a - &c);//err
return 0;
}
间接寻址运算符
一旦使用指针指向了对象,就可以使用*(间接寻址运算符)访问存储在对象中得到内容。
例如以下操作
int a=10;
int *p=&a;
//*p就是指向了a内存地址
//另外多说一句,不要把寻址运算符用于未初始化的指针变量。如果指针变量p,没有初始化,
//那么访问p的值就会导致未定义的行为
指针和数组
#include
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0; }
如图所示,你可见数组名和数组首元素的地址是一样的。
于是我们这压根写代码也是可行的。
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;//p存放的是数组首元素的地址
通过上述的描述,我们也可以通过指针来访问数组
#include
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr)/sizeof(arr[0]);
for(i=0; i<sz; i++)
{
printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i);
}
return 0; }
所以 p+i 其实计算的是数组 arr 下标为i的地址。
那我们就可以直接通过指针来访问数组。
int main(){
int arr[10]={1,2,3,4,5,6,7,8,9,10}
int sz=sizeof(arr)/sizeof(arr[0]);
int *p=arr;
int i = 0;
for (i = 0; i<sz; i++)
{
printf("%d ", *(p + i));
}
return 0;
}
指针变量也是变量,是变量 有地址,那指针变量的地址存放在哪里?
这就是 二级指针 。
换言之,就是存储指针变量的数组。
我画一个示意图,你们来体验一下
了解过二级指针,我们来看看二级指针的运算有哪些。
int b = 20;
*pa = &b;//等价于 p = &b;
**pa = 30;
//等价于*p = 30;
//等价于a = 30;