C Primer Plus: Arrays and Pointers (C10-1)

You will learn:

  • keyword
    static
  • Operators:
    & * (unary)
  • How to create and initialize arrays
  • Pointers
  • Writing Functions that process arrays
  • Two-dimensional arrays

Arrays

An array is composed of a series of elements of one data type.

记住数组最大的特点:在内存中连续存放,有顺序。

Declare arrays

Float candy[365];
char code[12];
int states[50]
  • 数组从0开始计数,用 candy[0] 表示第 1 个元素, candy[364] 表示第 365 个元素。

Initialization

int powers[8] = {1, 2, 3, 4, 5, 6, 7, 8};
...

Listing 10.1 presents a short program that prints the number of days per month

#include <stdio.h>
#define MONTHS 12

int main()
{
    int days[MONTHS] = {31, 28, 31, 30, 31,30, 31,31, 30, 31, 30, 31 };
    int index;

    for (index = 0; index < MONTHS; index++)
        printf("Month %d has %2d days.\n", index + 1, days[index]);

    return 0;
}

Output

➜  C10_ArraysAndPointers ./a.out 
Month 1 has 31 days.
Month 2 has 28 days.
Month 3 has 31 days.
Month 4 has 30 days.
Month 5 has 31 days.
Month 6 has 30 days.
Month 7 has 31 days.
Month 8 has 31 days.
Month 9 has 30 days.
Month 10 has 31 days.
Month 11 has 30 days.
Month 12 has 31 days.

Using const with Arrays

const int days[MONTHS] = {31, 28, 31, 30, 31,30, 31,31, 30, 31, 30, 31 };

Now it is a read-only array.

定义数组的时候要初始化,否则数组可能为任何值,及原本处于对应数组内存位置的值。

定义数组时可以不指定元素个数,由编译器自动计算

const int days[] = {31, 28, 31, 30, 31,30, 31,31, 30, 31, 30, 31 };

在这种情况下,可以在 for 循环中用 sizeof <数组名> / sizeof <数组名[0]> 计算数组元素个数:

for (index = 0; index < sizeof days / sizeof days[0]; index++)
	...

Designated Initializers (C99)

C99 added a new capability: designated initializers. This feature allows you to pick and choose which elements are initialized.

简单来说,就是你可以挑选数组中的任意值进行初始化。并且其它没有初始化的元素将被自动设为默认值(如 0,空字符等)
下面两条语句等价:

int arr[6] = {0, 0, 0, 0, 0, 212};
int arr[6] = {[5] = 212};

Listing 10.5

#include <stdio.h>
#define MONTHS 12

int main()
{
    int days[MONTHS] = {31, 28, [4] = 31,30,31,[1] = 29 };
    int index;

    for (index = 0; index < MONTHS; index++)
        printf("Month %d has %2d days.\n", index + 1, days[index]);

    return 0;
}

Output

➜  C10_ArraysAndPointers ./a.out 
Month 1 has 31 days.
Month 2 has 29 days.
Month 3 has  0 days.
Month 4 has  0 days.
Month 5 has 31 days.
Month 6 has 30 days.
Month 7 has 31 days.
Month 8 has  0 days.
Month 9 has  0 days.
Month 10 has  0 days.
Month 11 has  0 days.
Month 12 has  0 days.

以上程序看出

  1. 当初始化第五个元素后,后面默认初始化后面的元素,除非指定第几个元素。
  2. 如果某个元素初始化了多次,则最后一次的初始化生效(编译器会提警告)。

Assigning Array values

After an array has been declared, you can assign values to array members by using an array index.

数组可以通过使用索引赋值。

...
a[2] = 3;
...

数组名的值即为数组第一个元素的地址。

#include <stdio.h>
#define SIZE 5

int main()
{
    int envs[SIZE] = {1, 2,3, 4, 5};
    int i;

    printf("The value of envs is %p\n", envs);

    for (i = 0; i < SIZE; i++){
        printf("%p >>> %d\n", &envs[i], envs[i]);
    }

    return 0;
}

Output

➜  C10_ArraysAndPointers ./a.out   
The value of envs is 0x16bc73610
0x16bc73610 >>> 1
0x16bc73614 >>> 2
0x16bc73618 >>> 3
0x16bc7361c >>> 4
0x16bc73620 >>> 5

数组只有在初始化时候可以整体赋值。初始化以后,只能对各个元素单独操作
下面的程序展示了几种数组的错误操作方式:

#include <stdio.h>
#define SIZE 5

int main(void)
{
    int oxen[SIZE] = {5, 3, 2, 8};
    int yaks[SIZE];
    
    yaks = oxen; // not allowed
    yaks[SIZE] = oxen[SIZE]; // out of range
    yaks[SIZE] = {5, 3, 2, 8}; // doesn't work
    return 0;
}

Array Bounds

C语言编译器不检查数组越界!!!

#include <stdio.h>
#define SIZE 5

int main(void)
{
    int oxen[SIZE] = {5, 3, 2, 8};

    for(int i = 0; i < SIZE + 2; i++)
    {
        printf("%d >>> %d\n", i, oxen[i]);
    }
    return 0;
}

Output

➜  C10_ArraysAndPointers ./a.out   
0 >>> 5
1 >>> 3
2 >>> 2
3 >>> 8
4 >>> 0
5 >>> 1 // out of range
6 >>> -374800268 // out of range

C trusts the programmer to do the coding correctly and rewards the programmer with a faster program.

下面的程序逆向输出斐波那契数列

#include <stdio.h>
#define SIZE 10

int main(void)
{
    int feibo[SIZE] = {1, 1};

    for(int i = 2; i < SIZE; i++)
    {
        feibo[i] = feibo[i-1] + feibo[i-2];
    }

    for(int i = 0; i < SIZE; i++)
    {
        printf("feibo %d >>>>> %d\n", i+1, feibo[i]);
    }

    int i = 0;
    int j = sizeof feibo / sizeof feibo[0] - 1;
    int tmp;

    while (i < j)
    {
        tmp = feibo[i];
        feibo[i] = feibo[j];
        feibo[j] = tmp;
        i++;
        j--;
    }

    printf("inverse the feibo sequence...\n");

    for(int i = 0; i < SIZE; i++)
    {
        printf("feibo %d >>>>> %d\n", i+1, feibo[i]);
    }
    return 0;
}

Output

➜  C10_ArraysAndPointers ./a.out   
feibo 1 >>>>> 1
feibo 2 >>>>> 1
feibo 3 >>>>> 2
feibo 4 >>>>> 3
feibo 5 >>>>> 5
feibo 6 >>>>> 8
feibo 7 >>>>> 13
feibo 8 >>>>> 21
feibo 9 >>>>> 34
feibo 10 >>>>> 55
inverse the feibo sequence...
feibo 1 >>>>> 55
feibo 2 >>>>> 34
feibo 3 >>>>> 21
feibo 4 >>>>> 13
feibo 5 >>>>> 8
feibo 6 >>>>> 5
feibo 7 >>>>> 3
feibo 8 >>>>> 2
feibo 9 >>>>> 1
feibo 10 >>>>> 1

C99 中不允许使用变长数组。
C11可以使用变长数组。

int n = 10;
float arr[n]; // not allowed before C99.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值