前言
这是我自己的学习指针后做的笔记,提供给大家看看,有什么错可以在评论区和我说呀比较基础,感谢大家提点
内存和地址
每一的数据在电脑内会存放在内存里
变量在不同的系统中的大小也不同
32位编译器: char: 1 字节 char*: 4 字节 short int: 2 字节
int: 4 字节 float: 4 字节 double: 8 字节
long: 4 字节 long long: 8 字节
64位编译器: char: 1 字节 char*: 8 字节 short int: 2 字节
int: 4 字节 float: 4 字节 double: 8 字节
long: 8 字节 long long: 8 字节
而要找到这个内存就要给他表一个序号,地址就是内存的序号,可以通过地址来找到相应的内存
指针变量
指针是一个变量,用来存放地址
整型指针 int* p
字符串指针 char* p
数组指针 int* p[] char* p[]
函数指针 int(*p)(type,type) (type是传参的类型)
结构体指针 struct name *p (name为结构体的命名)
无类型指针/无返回值指针 void* p
void *p; // 可以指向任何类型的数据
int a = 10;
char c = 'A';
p = &a; // 指向int
p = &c; // 指向char
printf("%d", *(int*)p);// 使用时需要类型转换
设置指针
*(解引⽤操作符)
#include <stdio.h>
int main()
{
int a = 10;
int * pa = &a;//(整型指针,&为取地址符号,取出a变量的地址)
printf("%d",a);//打印10
printf("%d",*pa);//打印也10
*pa=100//改变a值为100
printf("%d",*pa);// 再打印为100,
return 0;
}
字符串指针
char *str = "Hello"; // 字符串常量,不可修改
char arr[] = "Hello"; // 字符数组,可以修改
// str[0] = 'h'; // 错误!字符串常量不可修改
arr[0] = 'h'; // 正确
指针运算
指针加减一个整数时,指针增加的大小与他是什么指针类型有关
设int类型指针 int* p=0X00001,p+1就是再加4( p+1=0X00001+sizeof(int))
变为0X00005(地址一般用16进制表示)
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);//计算arr数组内有多大少元素
for(i=0; i<sz; i++)
{
printf("%d ", *(p+i));
}
return 0;
}
const 修饰指针
const修饰的变量不可以直接改变,如下
int main()
{
const int a = 10;
int* pa = &a;
printf("%d\n",a);
//a = 100;//编译器报错,报:表达式必须是可修改的左值
*pa = 100;//用地址找到a并且改变不会报错
printf("%d\n", a);
return 0;
}
const修饰的指针变量:
int const * p;//const 放在*的左边做修饰p这个指针指向的变量
int * const p;//const 放在*的右边做修饰p这个指针
野指针
1.未初始化指针而使用 -->初始化指针 int*p=NULL
(NULL表示指针或值不指向任何有效的内存位置或对象)
2.指针越界访问别的内存 --> 防止越界访问
3.指针释放未给值 -->释放后给值NULL,并在再次使用时用assert断言变量是否为NULL
数组指针
int arr[]={1,2,3,4,5};
int* p=arr;
int(*pa)[5]=&arr;//&arr是int(*)[5]的整型数组指针,所以用整型数组指针来接收,使pa指向arr数组
printf("p = %p\n", p); // 指向第一个元素的地址
printf("p+1 = %p\n", p+1); // 指向第二个元素,地址+4字节
printf("pa = %p\n", pa); // 指向整个数组的地址
printf("pa+1 = %p\n", pa+1); // 指向下一个数组,地址+20字节
数组名就时数组首元素的地址(在sizeof()内单独存在时表示整一个数组)
arr[0]其实等价于*(p+0),而&arr表示整个数组的地址
使用数组指针访问数组:
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3 };
int* pa = arr;
size_t sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
printf("%d ", *(pa + i));
}
for (int i = 0; i < sz; i++)
{
printf("%d ", pa[i]);
}
return 0;
}

一维数组的传参本质:
一维数组传参时实参传的是数组首元素的地址,所以形参可以用相应的指针接受
type (*p),(type是指针的类型,a为每行数组的元素个数)来接收
最好把数组的元素个数一起传过来,防止指针越界访问,变成野指针
二维数组的传参本质:
二维数组在传参时是将二维数组的第一行的数组地址穿出
用 type(*pa)[a] 来接收
二级指针
指针也是变量,也有地址,指向指针地址的指针就是二级指针
int arr[]={0};
int* p=arr;
int* pa=&p;
指针数组:
数组指针是指针---- int (*p)[]=a
而指针数组是数组---- int* p[]={&a} , 该数组内存放的是相应类型的地址
用指针数组实现二维数组:
int arr1[] = {1,2,3,4,5};
int arr2[] = {2,3,4,5,6};
int arr3[] = {3,4,5,6,7};
int* pa[3]={arr1,arr2,arr3};
int i = 0;
int j = 0;
for(i=0; i<3; i++)
{
for(j=0; j<5; j++)
{
printf("%d ", pa[i][j]);//打印出相应的数
}
printf("\n");
}
pa[1][2]理解----> *(*(pa+1)+2 )
(pa+1)指向pa数组的第二个元素arr2
*(pa+1)得到arr2,即arr2数组首元素的地址,
*(pa+1)+2指向arr2的第三个数组
即*(*(pa+1)+2 )为arr2的第三个元素--- 4
函数指针数组
函数指针数组是一个存放函数指针的数组,本质是数组
用于转移表,如下,将每一种计算方法放在一个数组内进行调用
#include <stdio.h>
#include <windows.h>
void menu()
{
printf("************************\n");
printf("***** 1.+ 2.- *******\n");
printf("***** 3.* 4./ *******\n");
printf("***** 0.exit *******\n");
printf("************************\n");
}
int Add(int x, int y)
{
return x + y;
}
int Sud(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
int main()
{
int i = 0;
int (*pf[5])(int, int) = { NULL,Add,Sud,Mul,Div};
int x, y;
do
{
menu();
printf("请选择:");
scanf("%d", &i);
if (i >= 1 && i <= 4)
{
printf("请输入两个参数:");
scanf("%d%d", &x, &y);
int r = pf[i](x, y);
system("cls");
printf("r = %d\n", r);
}
else if (i == 0)
printf("退出\n");
else
{
system("cls");
printf("输入错误,请重新输入\n");
}
} while (i);
return 0;
}
回调函数
将函数a穿个函数b,函数b用函数指针接收并在函数b中调用函数a
运用回调函数的冒泡排序
#include <stdio.h>
void Intexchange(int* x, int* y)
{
int a = *x;
*x = *y;
*y = a;
}
void Exchange(int* p, void(*p)(int*,int*),int sz)
{
int i, j;
for (i = 0; i < sz - 1; i++)
{
for (j = 0; j < sz - i - 1; j++)
{
if (p[j] > p[j + 1])
q(p+j, p+j+1);
}
}
}
void Print(int* p, int i)
{
int j;
for (j = 0;j < i; j++)
{
printf("%d ", p[j]);
}
}
int main()
{
int arr[] = { 9,8,7,6,5,4 };
size_t sz = sizeof(arr) / sizeof(arr[0]);
Print(arr, sz);
printf("\n");//打印 9 8 7 6 5 4
Exchange(arr, Intexchange,sz);
Print(arr, sz);//打印 4 5 6 7 8 9
return 0;
}
C语言指针核心概念解析
15万+

被折叠的 条评论
为什么被折叠?



