//首发个人公众号 :Linux驱动
写在前面的话,
数组在linux源码里面直接使用的比较简单,也有放在结构体里面使用的。但是却是在求职(指的是校招类的,社招的不清楚)笔试中却大量使用,尤其和指针放在一起的时候。下面是阅读《c和指针》第8章—数组的笔记。我个人感觉看这些知识点的时候可以带个小问题去阅读书籍效果比较好一点,比看干巴巴的文字比较好一点。
首先放一道看到的题目
#include<stdio.h>
#include<stdlib.h>
int main()
{
char *a[] = { "work", "at", "alibaba" };
char **pa = a;
pa++;
printf("%s\n", *pa);
system("pause");
return 0;
}
答案是:at
分析:
char *a[] = { “work”, “at”, “alibaba” };
1>a[],可以写成a[3],使用”[]”是为让内存自动计算分配的空间,很明显这儿分了3个数组。
2>a是一个数组,它的类型是char型的指针,它指向的是数组的首地址,就是&a,a的地址为&a[0],就是”work”的地址。这就a的值,&a[0]。
3>这些知识用内存四区(栈区、堆区、常量区,代码区,这部分后面的文章会写的,专门用来理解指针和内存泄漏等问题的分析理解)。指针数组a存储的常量区{ “work”, “at”, “alibaba” }的首地址,因为是在常量区,所以对a++等操作就是对整个{ “work”, “at”, “alibaba” }的地址的操作,这样肯定是不行的,这个得从编译器的角度来思考,代码的编译之前会分配内存,所以代码过程中不能再改变这个地址。所以a++这种操作是错误的。可以用直接用a[0],a[1],a[2]读取数组a的值。
4>还有一种间接操作的方法,就是指针,数组a存储的已经是char 的指针了,简介操作指针就是指针的指针,二级指针。char **pa = a; pa存放的(或者指向的)是数组a的地址,a的地址就是”work”的地址,对指针pa++,就指向”at”了。
5>pa的值还可以表示为pa[0],(a+1),a[1]。
运算结果:
一维数组:
- 数组的申明
int a;
int b[10];
分析:
1>a是int型变量,好理解;b是int型数组,也好理解。
b[0]里面存放数组的第一个int型值,b[1]存放第二个,依次类推。
2>b 是数组名字,数组名b是一个“指向int的常量指针”,注意是常量,不是变量。代表的是数组第一个元素的地址。
- 数组的赋值
int a[10];
int b[10];
int *c;
考虑下面的表达式的合法性;
c = &a[0];
c = a;
//指针c 指向a的首元素地址,即c = &a[0],同时a就代表首元素地址。所以前面这俩表达式可以互换。
b = a;
a = c;
//a,b都是相应数组的首元素的地址,是常量指针,所以不能不能进行+ ,-,=的操作。
b =a ;是想表达俩数组元素的互换,可以使用循环b[i] = a[i]操作。
- 数组的下标引用
1>有个公式:
array[id] = *(array + (id) ) //看下面的讨论
2>* (优先级) > +(优先级) //查表得
讨论:
Int b[10];
*(b + 3)
分析:首先b是一个int型指针,指向的是&b[0],所以3是根据int型的长度来移动的,指向的是第3个元素的地址,所以(b + 3) 是 &b[3],所以*(b + 3) 就是 b[3]。
结论:使用下标的地方(b[3])可以使用指针表达式( *(b +3) )。
举例说明:`
Int array[10];
Int *ap = array +2;
需要理解的部分,判断合法嘛,如果合法看看还有什么能够后表达相同的意思
(不要看答案自己思考一下):
ap
*ap
ap[0]
ap + 6
*ap + 6
*(ap +6)
&ap
ap[ - 1]
答案如下:
ap 合法,还可以写成:array +2 ,&array[2]。
*ap 合法,还可以写成:*(array +2) ,array[2]。
ap[0] 合法,还可以写成: *ap ,*(ap + 0),*(array +2) ,array[2]。
ap + 6合法,还可以写成:array +8 ,&array[8]。
*ap + 6 2>* (优先级) > +(优先级) //查表得
合法,还可以写成:array[2] +6
*(ap +6)合法,还可以写成:array[8]
&ap 合法,内存地址随机
ap[ - 1]合法,还可以写成:array[1]