数组和指针
(1)笔记
1 用数组前必须先初始化它,C不允许把数组作为一个单元赋给另一个数组,除初始化以外也不允许使用花括号列表的形式赋值。
/* 一些无效的数组赋值 */
#define SIZE 5
int main(void)
{
int oxen[SIZE] = {
5, 3, 2, 8}; /* 初始化没问题 */
int yaks[SIZE];
yaks = oxen; /* 不允许 */
yaks[SIZE] = oxen[SIZE]; /* 数组下标越界 */
yaks[SIZE] = {
5, 3, 2, 8}; /* 不起作用 */
}
2 使用越界下标的结果是未定义的。
3 指针加1指的是增加一个存储单元。
4 *运算符优先级高于+运算符
*(dates + 2) // dates第3个元素的值
*dates + 2 // dates第1个元素的值加2
5 函数原型可以省略参数名,函数定义中不能省略。
6 [注]千万不要解引用未初始化的指针。
int *pt; // 未初始化的指针
*pt = 5; // 严重的错误
第2行的意思是把5存储在pt指向的位置。但是pt未被初始化,其值是一个随机值,这可能会导致擦写数据或代码,或者导致程序崩溃。(创建一个指针时,系统只分配了储存指针本身的内存,并未分配储存数据的内存。)
7 可以把const数据或非const数据的地址初始化位指向const的指针或为其赋值。只能把非const数据的地址赋给普通指针(否则可以通过修改指针来改变const数组中的数据)。
8 []的优先级高于*
int (*pz) [2]; // pz指向一个内含两个int类型值的数组
int *pax[2]; // pax是一个内含两个指针元素的数组,每个元素都指向int的指针
9
int *pt;
int (*pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2;
pt = ar1; // 无效 pt指向一个int类型值,而ar1指向一个内含3个int类型元素的数组
pa = ar2; // 无效 pa指向一个内含3个int类型元素的数组,而ar2指向一个内含2个int类型元素的数组
p2 = ar2; // 无效 p2是指向指针的指针 而ar2是指向数组的指针,该数组内含2个int类型的元素
*p2 = ar2[0]; // 有效 都是指向int的指针
10 变长数组
int quarters = 4;
int regions = 5; // 在声明变长数组时先需要声明形参
double sales[regions][quarters]; // 一个变长数组(VLA)
C语言中变长数组的限制:必须是自动存储类别,意味着无论在函数中声明还是作为函数形参声明,都不能使用static和extern存储类别说明符,而且不能在声明中初始化它们。
[注]:变长数组不能改变大小,“变”字指的是可以用变量指定数组的维度。
11 复合字面量 (必须在创建的时候使用)
(2)习题 10.13
10.1
/* 计算每年的总降水量、年平均降水量和5年中每月的平均降水量 */
#include<stdio.h>
#define MONTHS 12 // 一年的月份
#define YEARS 5 // 年数
int main(void)
{
// 用2010~2014年的降水量数据初始化数组
const float rain[YEARS][MONTHS] =
{
{
4.3, 4.3, 4.3, 3.0, 2.0, 1.2, 0.2, 0.2, 0.4, 2.4, 3.5, 6.6},
{
8.5, 8.2, 1.2, 1.6, 2.4, 0.0, 5.2, 0.9, 0.3, 0.9, 1.4, 7.3},
{
9.1, 8.5, 6.7, 4.3, 2.1, 0.8, 0.2, 0.2, 1.1, 2.3, 6.1, 8.4},
{
7.2, 9.9, 8.4, 3.3, 1.2, 0.8, 0.4, 0.0, 0.6, 1.7, 4.3, 6.2},
{
7.6, 5.6, 3.8, 2.8, 3.8, 0.2, 0.0, 0.0, 0.0, 1.3, 2.6, 5.2}
};
int year, month;
float subtot, total;
printf(" YEAR RAINFALL (inches)\n");
for (year = 0, total = 0; year < YEARS; year++)
{
// 每一年,各月的降水量总和
for (month = 0, subtot = 0; month < MONTHS; month++)
subtot += *(*(rain + year) + month);
printf("%5d %15.1f\n", 2010 + year, subtot);
total += subtot; // 5年的总降水量
}
printf("\nThe yearly average is %.1f inches.\n\n", total / YEARS);
printf("MONTHLY AVERAGES:\n\n");
printf(" Jan Feb Mar Apr May Jun Jul Aug Sep Oct ");
printf(" NOV Dec\n");
for (month = 0; month < MONTHS; month++)
{
// 每个月,5年的总降水量
for (year = 0, subtot = 0; year < YEARS; year++)
subtot += *(*(rain + year) + month);
printf("%4.1f ", subtot / YEARS);
}
printf("\n");