指针
- 指针是存放地址的,可以理解为:指针就是地址
- 指针不管什么类型都是4个字节(32位平台)/8个字节(64位平台)
- 指针的类型决定了±时候的字节数、解引用时的权限,指针+1是加上它自身的大小
- 指针也是一种类型
数组
- 数组传参时会降维,降成指针,其类型时数组元素的类型。
- 所有数组都可以表达成一维数组的形式
- 除了sizeof(arr)和&arr这两种情况表示整个数组,其余几乎全部代表的是首元素地址
- arr和&arr表达的地址是一样的,但是意义又不同。给&arr+1表示给首元素的地址加上一整个数组的大小,arr+1表示给首元素加上一个数组元素的大小
- 数组只可以省略第一个[]的数字
char * str1 = "student"
char* str2 = "student"
char arr1[] = "student"
char arr2[] = "student"
- str 是一个char* 类型的变量,即指针变量,里面存放着‘student’首元素的地址。或者说str指向字符串首元素,而*str = ‘s’。字符串在内存中的字符常量区。
- arr是一个数组名,数组开辟在函数的栈帧上,调用则创建,结束则释放(不是清空,是等新的数据覆盖)。
- 所以这么看来,str1 == str2, arr1 != arr2,是因为str1和str2是指向同一块内存空间,而数组是独立开辟的内存空间,arr1和arr2所指向首元素的地址不同。
指针和数组完全不同的两个概念,仅仅是相似的用法
指针数组
int *p[]
因为 [] > * 的优先级,所以p这是一个数组,数组中存放了指针类型的元素。
数组指针
int arr[10] = {1,2,3,4,5};
int (*p)[10] = &arr;
p本质是一个指针,指向int类型的数组。p中存放的是数组的地址(&arr)。
传参栗子:
#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)
{
int i = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{ printf("%d ", arr[i][j]); }
printf("\n");
}
}
void print_arr2(int (*arr)[5], int row, int col)
{
int i = 0;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
printf("%d ", arr[i][j]);
} printf("\n");
}
}
int main()
{
int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
print_arr1(arr, 3, 5);
print_arr2(arr, 3, 5);
return 0;
}
栗子:
int (*p[10])[10]; //指针数组的数组指针
int(*pp)[10] --数组指针(本质)
*p[10] – 指针数组
传参
数组:数组传参降维成指针
指针数组(int *arr[10]):**arr
一维数组:arr[]、arr[10]、*arr、
二维数组:arr[3][5]、arr[][5]、*arr[5]、(*arr)[5]、**arr
一级指针:不变
二级指针:&一级指针、二级指针、指针数组/多维数组
按我自己理解吧,*和&是一对可以抵消的,就是*(&p) = p;
函数指针
- int (*pf)(int) = &fun
- 它是用来保存函数的地址
- 必须初始化,即指向一个函数
调用函数:
ans = fun(25);
ans = (*pf)(25);
ans = pf(25);
应用:
回调函数:用函数指针传函数1到另一个函数2中,执行到相应语句就可以通过函数指针调用函数1.
将几个功能相似参数个数相同但参数类型不同的函数融合在一起,应用起来更加灵活。//注意将函数指针所指向得函数参数转化为正确的类型。
例如,比较函数,传入int、char参数会调用不同的函数。
指针函数
- void *fun()
栗子:
(* (void (* )())0)();
//函数指针类型的函数的指针
void (signal(int , void()(int)))(int);
//参数是int和函数指针的函数的指针
函数指针数组
int (*p[10])(int) //在数组中存放函数得地址
应用:
袖珍计算器,把 + - * /四个功能函数地址放在一个’计算机‘数组里,节省空间。
指向函数指针数组的指针
int (*(*p)[10])();
练习题
strlen:求字符串长度,以‘\0’结尾但不包含‘\0’,参数是char*,是给定的开始计数的位置。
sizeof:求字符串长度时,包含‘\0’,是用总的字符串长度除以类型所占字节。
- char arr[] = {‘a’,‘b’,‘c’,‘d’};
strlen(arr)——没有\0,不能确定但能运行出来,假设计数到10
strlen(*arr)——参数类型与char *不符
strlen(&arr+1)——指向下一个数组的首元素,是一个指针,返回字节是4
strlen(&arr[0]+1)——&arr[1],从第二个元素开始数,返回9 - char arr[] = “abcdef”;
sizeof(arr+0)——&arr[0],是地址,返回4个字节
sizeof(*arr)—— * &arr[0]->arr[0],char型返回一个字节