码字不易,对你有帮助 点赞/转发/关注 支持一下作者
微信搜公众号:不会编程的程序圆
看更多干货,获取第一时间更新
代码,练习上传至:https://github.com/hairrrrr/C-CrashCourse
0. 指针与数组
C 语言中数组与指针这两个概念之间的联系密不可分。
关于数组:
- C 语言中只有一维数组,而且数组大小必须在编译期就作为一个常数确定下来。数组元素可以是任何类型的对象,也可以是另外一个数组。(C99 允许变长数组)
- 对于一个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为 0 的元素的指针。
任何一个数组下标运算都等同于一个对应的指针运算。
声明数组
int a[3];
声明了一个拥有 3 个整型元素的数组。
struct{
int p[4];
double x;
}b[14];
声明了一个拥有 17 个元素的数组,且每个元素都是一个结构。
int calendar[12][31];
声明了拥有 12 个数组类型的元素,其中每个元素都是拥有 31 个整型元素的数组。因此 sizeof(calendar)
的值是 12x31 与 sizeof(int)
的乘积。
关于指针
任何指针都是指向某种类型的变量。
int *ip;
表明 ip 是一个指向整型变量的指针。
我们可以将整型变量 i 的地址赋值给指针 ip :
int i;
ip = &i;
如果我们给 *ip 赋值,就可以改变 i 的取值:
*ip = 17;
数组与指针
如果一个指针指向的是数组中的一个元素,那么我们只要给这个指针加 1,就能够得到指向该数组中下一个元素的指针。减法同理。
如果两个指针指向的是同一个数组中的元素,那么两个指针相减是有意义的:
int *q = p + i;
我们可以通过 q - p 得到 i 的值。
int a[3];
int* p = a;
数组名被当作指向数组下标为 0 的元素的地址。
注意,我们没有写成:
p = &a;
这样的写法在 ANSI C 中是非法的,因为 &a
是一个指向数组的指针,而 p 是指向整型变量的指针,它们了类型并不匹配。
继续我们的讨论,现在 p 指向数组 a 中下标为 0 的元素,p + 1 指向下标为 1 的元素,以此类推。如果希望 p 指向下标为 1 的元素,可以这样写:
p = p + 1;
当然,也可以这样写:
p++;
*a
是数组 a 中下标为 0 的元素的引用。同理,*(a + 1)
是数组中下标为 1 的元素的引用,*(a + i)
是数组中下标为 i 的元素的引用,简写为 a[i]
。
由于 a + i
和 i + a
的含义一致,因此a[i]
和i[a]
也具有相同的含义。但我们绝不推荐这种写法。
二维数组
int calendar[12][31];
请思考,calendar[4]
含义是什么?
calender[4]
是 calendar 数组第 5 个元素,是 calendar 数组 12 个拥有着 31 个整型元素的数组之一。sizeof(calendar[4])
大小为 31 与 sizeof(int)
的乘积。
p = calendar[4];
这个语句使 p 指向了数组 calendar 下标为 0 的元素。
如果 calendar 是数组,我们可以:
i = calender[4][7];
上式等价于:
i = *(calender[4] + 7);
等价于:
i = *(*(calender + 4) + 7);
下面我们再看:
p = calender;
这个语句是非法的。因为 calendar 是一个二维数组,即数组的数组,calendar 是一个指向数组的指针,而 p 是指向整型变量的指针。
我们需要声明