20190329-C语言学习-指针与数组的暧昧关系(下标运算符 | 数组名的本质|指针数组与数组指针

2019-07-13 08:05发布

写在前面的话:本文章的内容是对王利涛老师的《C语言嵌入式Linux编程》系列课程的学习笔记,王老师讲得很好,清晰易懂,写这个博客仅处于学习用途。   目录 下标运算符 对数组的打印有几种方式 为什么指针可以使用[]访问数组?p[i] 为什么数组可以使用*访问数组元素?*(a+i)        下标运算符 数组名的本质 底层实现机制 为什么对数组直接赋值?为什么只有在初始化的时候赋值? 数组名的本质 指针数组与数组指针 指针数组的数组元素是指针 char *season[4] ([]有更高的优先级) 数组指针是指向数组的指针 int(*pa)[4] 小结

下标运算符

指针和数组是不同的数据类型

对数组的打印有几种方式

#include "stdio.h" int main(){ int a[10]={1,2,3,4,5,6,7,8,9,10}; int *p=a; for(int i=0;i<10;i++){ printf("%d ",a[i]); } printf(" "); for(int i=0;i<10;i++){ printf("%d ",*(a+i)); } printf(" "); for(int i=0;i<10;i++){ printf("%d ",*(p+i)); } printf(" "); for(int i=0;i<10;i++){ printf("%d ",p[i]); } } 运行的结果完全一样 并且当函数传参是一个数组时,传入一个数组名还是指针名的效果也是完全一样的

为什么指针可以使用[]访问数组?p[i]

为什么数组可以使用*访问数组元素?*(a+i)

       下标运算符

因为C语言对下标运算符[]有如下的操作:E1[E2] ---> *(E1+E2) 也就是a[i] -->*(a+i)所以可以通用 因为对E1和E2没有正负限制,所以可以有如下的定义 下标运算符[]和不仅和数组有关 int i =10; int *p=&i; printf("%d ",1[&i-1] ==> *(1+&i-1) ==> *(&i) ==>10

数组名的本质

数组名代表了什么?底层如何实现?传参传了什么?

底层实现机制

  • mov r1, #5 这个就是数组的长度
传入的参数在arm中会先放入r0~r3,其余的才会放到栈中
  • ldr r0, [pc,#16] ; 104d8  是寄存器简介寻址,将104d8地址上的内容放入r0这个寄存器里面
在104d8中存在一个地址,00021028
  • 所以在传递参数的时候,是传递数组的首地址
  • 数组名是不等于常量指针的
数组名是有类型的,是不同的数据类型,传递的地址相同,碗和杯子装水的例子 老师举的例子 &a+1 ==> &a+1*(sizeof(a))

为什么对数组直接赋值?为什么只有在初始化的时候赋值?

数组名的隐式转换(在不同的时期有不同的意义)

数组名的本质

对于int b[4][20]而言,其实是一个有4个元素的一维数组,每一个数组元素都是有20个int组成的一维数组 所以int (*q)[20] 就是一个指针数组,指向的元素是元素有20个int的一维数组

指针数组与数组指针

指针数组的数组元素是指针 char *season[4] ([]有更高的优先级)

char *season[4] = {"spring","summer","autumn","winter"}; printf("hello %s",season[i])
  • 字符串在C语言中存放于rodata段中
  • 这个数组里存放的是字符串的元素的首地址

数组指针是指向数组的指针 int(*pa)[4]

  • 不同的指针类型, 1有不同的意义
  • 传递参数时
对于一维数组是数组首元素的地址,对于二维数组传递是首元素地址,首元素是一个指向数组的指针
  • 对于main函数
int main(void) int main(int argc, char *argv[]) 是一个指针数组

小结

听完这节课之后,我对指针和数组有了更清楚的了解。并且项目中遇到的一些不清楚的表达也清晰了很多。我觉得最近自己的记忆力在衰退,很多东西都是看了,理解了但是还是会忘记,还是要多多复习呢,多多动手!