Part1
1、指针的基本概念
指针变量也是一种变量,这种变量是用来存放地址的,指针变量也被简称为指针。
指针变量的大小:32位条件下4字节,64位条件下为8字节。
2、指针变量类型的意义
结论:指针的类型决定了对指针解引用的时候有多大的权限(即一次可以操作几个字节),比如,char*类型的指针解引用一次只能访问一个字节,int*的指针解引用就能访问四个字节。
指针+-整数:指针的类型决定了指针向前或者向后走一步有多大(距离)。
3.void*指针
可以理解为无具体类型的指针(泛型指针),可以用来接受任意类型的地址。
局限性:不能直接进行指针的+-整数和解引用的运算。
应用:一般使用在函数参数的部分,用来接收不同数据类型的地址,可以实现泛型编程的效果。
4.const修饰指针
总结:
(1)const如果放在*左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变,但是指针变量本身的内容可变。
(2)const如果放在*右边,修饰的是指针变量本身,保证指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。
5.指针运算
(1)指针+-整数:加或减去所n个指向类型的字节数。
(2)指针-指针:结果为两指针间所占的此类型的元素个数。
(3)指针的关系运算:
#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]);
while (p < arr + sz)
{
printf("%d", *p);
p++;
}
return 0;
}
6.野指针
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的。
6.1野指针成因
(1)指针未初始化;
(2)指针越界访问;
(3)指针指向的空间释放;
6.2如何规避野指针
(1)指针初始化;
(2)小心指针越界;
(3)指针变量不再使用时,及时置NULL,指针使用前检查有效性:
#include<stdio.h>
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* p = &arr[0];
for (int i = 0; i < 10; i++)
{
*(p++) = i;
}
//此时p已经越界
p = NULL;
p = &arr[0];
if (p != NULL)
{
//...
}
return 0;
}
(4)避免返回局部变量的地址;
7.assert断言
assert(p != NULL);
上⾯代码在程序运⾏到这⼀⾏语句时,验证变量 p 是否等于 NULL 。如果确实不等于 NULL ,程序继续运⾏,否则就会终⽌运⾏,并且给出报错信息提⽰。
#define NDEBUG
#include <assert.h>
然后,重新编译程序,编译器就会禁⽤⽂件中所有的 assert() 语句。如果程序⼜出现问题,可以移
int (*p)[10];
#include <stdio.h>
void test(int a[3][5], int r, int c)
{
int i = 0;
int j = 0;
for(i=0; i<r; i++)
{
for(j=0; j<c; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {{1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7}};
test(arr, 3, 5);
return 0;
}
3.函数指针变量
函数指针类型解析:
typedef关键字:
typedef int(*parr_t)[5]; //新的类型名必须在*的右边
应用:简化代码
简化前:
void (*signal(int , void(*)(int)))(int);
简化后:
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);
4.函数指针数组
储存函数指针的数组。
应用:转移表
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int d(int a, int b)
{
return a / b;
}
int main()
{
int input = 0;
int (*p[5])(int, int) = { 0, add, sub, mul, d };
do
{
int ret = 0;
int a = 0;
int b = 0;
printf("1.add\n2.sub\n3.mul\n4.div");
scanf("%d", &input);
scanf("%d %d", &a, &b);
if (input >= 1 && input <= 4)
{
ret = p[input](a, b);
printf("%d\n", ret);
}
else if(input == 0)
{
printf("exit\n");
}
else
{
printf("again\n");
}
system("pause");
system("cls");
} while (input);
return 0;
}
5.回调函数
通过函数指针调用的函数。