#include <stdio.h>
#include <string.h>
指针
1、指针定义--pointer
编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值。
指针是用来存放地址的,地址是唯一标记一块地址空间的
指针的大小在32位平台是4个字节,在64位平台是8个字节
int main()
{
int a = 10;//a占4个字节
int *pa = &a;//拿到的是a的4个字节的首字节的地址 pa是指针变量
*pa = 15;
printf("%d\n", a);
return 0;
}
2、指针和指针类型
指针类型的意义
1、指针类型决定了 指针解引用的权限有多大
2、指针类型决定了 指针指针走一步能走多远(步长)
int main()
{
int * pa;
char * ch;
float * f;
printf("%d\n", sizeof(pa));//4
printf("%d\n", sizeof(ch));//4
printf("%d\n", sizeof(f)); //4
return 0;
}
int main()
{
int a = 0x11223344;
int *pa = &a;
*pa = 0;
printf("%d\n", *pa);
return 0;
}
int main()
{
int a = 0x11223344;
char * pc = &a; //只能解引用a变量的1个字节,内存2bit 44改为00
*pc = 0;
return 0;
}
int main()
{
int arr[10] = { 0 };
int * p = arr;
char * pc = arr;
printf("%p\n", p); //003efa9c
printf("%p\n", p + 1);//003efaa0 int 指针类型+4
printf("%p\n", pc);//003efa9c
printf("%p\n", pc+1);//003efa9d char 指针类型+1
return 0;
}
int main()
{
int arr[10] = { 0 };
//char *pc = arr;
int *p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*(p+i)=1;//下标为i的地址
}
return 0;
}
3、野指针--指针指向的位置是不可知的
3.1指针未初始化
int main()
{
//p是一个野指针
int * p;//p是一个局部的指针变量,局部指针变量不初始化的话,默认是随机值
*p = 20;//非法访问内存 //error
return 0;
}
3.2指针越界访问
int main()
{
int arr[10] = { 0 };
int *p = arr;
int i = 0;
for (i = 0; i <= 10; i++)
{
*p = i;
p++;
}
return 0;
}
3.3指针指向的空间释放--动态开辟
int test()
{
int a = 10;
return &a;
}
int main()
{
int *p = test();
*p = 20;
return 0; //error
}
3.4、如何规避野指针
3.4.1、指针初始化
int main()
{
//未明确赋值可直接初始化为 null
int *p = null;
明确知道初始化的值
int *prt = &a;
}
3.4.2、小心指针越界--c 语言本身不会检查数据的越界行为
3.4.3、指针指向空间释放即时置null
3.4.4、指针使用之前检查有效性
4、指针运算
4.1、指针+-整数
int main(){
#define n_values 5
float values[n_values];
float *vp;
for (vp = &values[0]; vp < &values[n_values];)
//指针的关系运算
{
*vp++ = 0;
//指针+整数
}
}
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *p = arr;
int *pend = arr + 9;
while (p <= pend)
{
printf("%d\n", *p);//1,2,3,4,5,6,7,8,9,10
p++;
}
return 0;
}
4.2、指针-指针 --指针减指针得到的是两个指针之间的元素个数
两个指针相减的前提: 两个指针指向同一块空间
int main()
{
int arr[10] = { 21, 63, 31, 49, 76, 63, 77, 58, 91, 10 };
char ch[5];
printf("%d\n", &arr[9] - &ch[0]);//error
printf("%d\n", &arr[9] - &arr[0]);//9--两个指针之前的元素个数
return 0;
}
strlen函数方法
int main()
{
int len = strlen("abc");
printf("%d\n", len);
}
计数器方法
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
递归法
指针减指针方法
int my_strlen(char *str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return str - start;//最后一个指针减第一个指针
}
int main()
{
int len = my_strlen("abc");
printf("%d\n", len);
}
4.3、指针的关系运算
5、指针和数组
int main()
{
int arr[10] = { 0 };
printf("%p\n", arr); //数组名是首元素的地址
printf("%p\n", &arr[0]);
ruturn 0;
}
int main()
{
int arr[10] = { 0 };
int *p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%p <==> %p\n", &arr[i], (p + i));
*(p + i) = i;
}
for (i = 0; i < 10; i++)
{
printf("%d\n",*(p+i));//0 1 2 3 4 5 6 7 8 9
}
return 0;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int *p = arr;
//[] 是一个操作符 2和arr是两个操作数
printf("%d\n", 2[arr]); //3
printf("%d\n", arr[2]); //3
//arr[2] --> *(arr+2)
printf("%d\n", *(p+2)); //3
printf("%d\n", 2[p]); //3
// arr[2] <==> *(arr+2) <==> *(p+2) <==> *(2+p) <==> *(2+arr) <==> 2[arr]
return 0;
}
6、二级指针 --"套娃指针"
int main()
{
int a = 10;
int *pa = &a;//pa是指针变量,一级指针;
int ** ppa= &pa;//pa也是个变量,&pa取出pa在内存中的起始地址;
printf("%d\n", *pa);
printf("%p\n", &a);
printf("%d\n", **ppa); //10
return 0;
}
7、指针数组
int main()
{
int arr[10];
char ch[5];
//指针数组
int * parr[5];//整型指针数组
char * pch[5];//字符指针数组
return 0;
}