学习目标:
学习内容:
遗忘内容
数组名表示的是数组首元素地址
但是有两个例外:
1)sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小
2)&数组名,数组名表示整个数组,取出的是整个数组的地址
指针类型决定了指针被解引用时访问的权限。
例如整形指针(int*)解引用4个字节;字符指针(char*)解引用1个字节…
指针类型决定了指针向前或者向后走一步,能走多大距离(字节)。
int* +1 --> +1sizeof(int)==+4
char +1 --> +1sizeof(char)==+1
int +n --> +nsizeof(int)==+n4
char* +n --> +nsizeof(char)==+n1
指针的注意事项(避免写出野指针)
1)指针不能像变量一样定义后不给赋值,如果没有值可赋,就赋值NULL
int* pa=NULL;
2)在函数中不能返回指针,因为函数中使用的指针仅限于函数体内,出了函数后那个指针生命周期就结束了。
int* test()
{
int a =10;
printf("%d\n",a);
return 0;
}
int main ()
{
int *p = test();
*p = 100;
return 0;
}
3)不要把指针指到定义的范围外
指针±整数:跳字节(根据指针类型的不同跳的字节也不同)指到下一个元素的位置。
例如:
指针可以相减
前提:指针-指针,两个指针必须指向同一块空间。
例如:&arr[4]-&ch[3]是错误的。
指针-指针的绝对值是两个指针之间元素的个数。
例如:&arr[9]-&arr[0]=9。
通过指针相减可以算出字符串中元素个数
#include<stdio.h>
int ge(char* ar)
{
char* start = ar;
while (*ar)
{
ar++;
}
return ar - start;
}
int main()
{
char arr[] = "asdvacx";
int n = ge(arr);
printf("%d\n", n);
return 0;
}
二级指针
#include<stdio.h>
int main()
{
int a = 0;//变量a赋值0
int* pa = &a;//一级指针,把a的地址存到pa里
int** paa = &pa;//二级指针,把pa的地址(存放地址的空间也有地址)存放到paa里
//以此类推还可以有三级指针
int*** paaa = &paa;
return 0;
}
指针数组:指针数组是一个数组,里面存放的是指针
//用于举例,实际应用中不这么写,没啥意义..
#include<stdio.h>
int main()
{
int a = 10;
int b = 13;
int c = 5;
int d = 17;
int e = 18;
int* arr[] = { &a,&b,&c,&d,&e };
for (int i = 0; i < 5; i++)
{
printf("%d\n", *(arr[i]));
}
return 0;
}
可以通过指针数组,构造成类似于二维数组的形式:
#include<stdio.h>
//虽然看上去很像二维数组,但是内核完全不一样
int main()
{ //创立三个数组
int data1[] = { 1,2,3,4,5 };
int data2[] = { 5,4,3,2,1 };
int data3[] = { 0,0,0,0,0 };
int* arr[] = { data1,data2,data3 };//把数组名放进去,代表把数组首元素地址放进去,所以arr是个指针数组
for (int i = 0; i < 3; i++)//i=0表示得到data1的首元素地址,i=1表示得到data2的首元素地址,i=2表示得到data3的首元素地址.
{
for (int j = 0; j < 5; j++)//当你得到data的首元素地址后,因为数组地址是连续的,就可以得到后面的地址
{
printf("%d ",arr[i][j]);//这里的arr[i]表示某个data的首元素地址,也就是说可以把arr[i]整体看作一个数组,那么想找到一个数组里的某个元素,就要在数组后加[下标],即加[j]
}
printf("\n");
}
return 0;
}