C语言 指针、数组、数组指针、函数指针、函数指针数组

指针

  • 指针是存放地址的,可以理解为:指针就是地址
  • 指针不管什么类型都是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’,是用总的字符串长度除以类型所占字节。

  1. char arr[] = {‘a’,‘b’,‘c’,‘d’};
    strlen(arr)——没有\0,不能确定但能运行出来,假设计数到10
    strlen(*arr)——参数类型与char *不符
    strlen(&arr+1)——指向下一个数组的首元素,是一个指针,返回字节是4
    strlen(&arr[0]+1)——&arr[1],从第二个元素开始数,返回9
  2. char arr[] = “abcdef”;
    sizeof(arr+0)——&arr[0],是地址,返回4个字节
    sizeof(*arr)—— * &arr[0]->arr[0],char型返回一个字节
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值