C Primer Plus(第10章)笔记与课后习题

本文是《C Primer Plus》第10章关于数组和指针的学习笔记,强调了初始化数组的重要性,指针操作的注意事项,如避免解引用未初始化的指针。此外,解释了变长数组的概念及其限制。文章还提到了一些C语言的规范,如函数原型的定义。最后,列出了14道课后习题,鼓励读者自行实践。
摘要由CSDN通过智能技术生成

数组和指针

(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");

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值