C语言高级教程之数组教程

  • 本文的编译环境
  • 一、前文:C语言数组(一、二)的链接
    • 1.1、C语言数组一文章链接
    • 1.2、C语言数组二文章链接
  • 二、数组的初始化
    • 2.1、数组的初始化的几种方式
  • 三、数组和地址
    • 3.1、数组和地址的关系
    • 3.2、输出数组的地址值
  • 四、确定数组的大小
    • 4.1、sizeof运算符确定数组的大小
    • 4.2、sizeof运算符输出数组所占的字节数
    • 4.3、sizeof运算符运用到for循环中
  • 五、完整程序
    • 5.1 Main.h 文件程序
    • 5.2 Main.c 文件程序
  • 六、总结

本文的编译环境

本文的编译环境使用的是集成开发环境:Visual Studio 2019

Visual Studio 2019官网链接如下

Visual Studio 2019官网链接

Visual Studio 2019集成的开发环境的特点有

  • Visual Studio 2019默认安装Live Share代码协作服务。
  • 帮助用户快速编写代码的新欢迎窗口、改进搜索功能、总体性能改进。
  • Visual Studio IntelliCode AI帮助。
  • 更好的Python虚拟和Conda支持。
  • 以及对包括WinForms和WPF在内的.NET Core 3.0项目支持等 。

一、前文:C语言数组(一、二)的链接

1.1、C语言数组一文章链接

在C语言数组(一)的教程中,简单的介绍了如下的几点

  • 介绍如何在C语言程序中使用数组。
  • 后在编写程序使用数组时,如何通过一个名称来引用一组数值。
  • 通过程序实例来掌握了C语言一维数组的定义,使用方法。

C语言数组(一)的文章链接如下所示

文章:C语言数组(一)

1.2、C语言数组二文章链接

在C语言数组(二)的教程中,简单的介绍了如下的几点

  • 介绍了C语言高级编程的数组的寻址方法。
  • 通过几个实例程序来掌握C语言数组寻址的应用。

C语言数组(二)的文章链接如下所示

二、数组的初始化

2.1、数组的初始化的几种方式

  • 可以给数组的元素指定初值,这可能只是为了安全起见。预先确定数组元素的初始值,更便于查找错误。
  • 为了初始化数组的元素,只需在声明语句中,在大括号中指定一列初值,它们用逗号分开。

例如:

double values[5] = { 1.5, 2.5,3.5, 4.5, 5.5 };
  • 这个语句声明了一个包含5个元素的数组value。
  • values[0]的初值是 1.5, value[1]的初值是2.5,依此类推。
  • 要初始化整个数组,应使每个元素都有一个值。
  • 如果初值的个数少于元素数,没有初值的元素就设成0。

因此如果编写

    double values1[5] = { 1.5, 2.5, 3.5 };
  • 前3个元素用括号内的值初始化,后两个元索初始化为0。
  • 如果没有给元素提供初值,编译器就会给它们提供初值0,所以初值提供了一种把整个数组初始化为0的简单方式。

只需要给一个元素提供0:

    double values2[5] = { 0.0 };
  • 整个数组就初始化为0.0。
  • 如果初值的个数超过数组元素的个数,编译器就会报错。

在指定一列初始值时, 不必提供数组的大小,编译器可以从该列值中推断出元素的个数。

    int primes[] = { 2, 3,5, 7,11, 13, 17, 19,23, 291 };
  • 上述语句中的数组大小由列表中的初始值个数来确定,所以primes数组有10个元素。

三、数组和地址

3.1、数组和地址的关系

下面声明了一个包含4个元素的数组:

long number[4];
  • 数组名称number指定了存储数据项的内存区域地址,把该地址和索引值组合起来就可以找到每个元素,因为索引值表示各个元素与数组开头的偏移量。
  • 声明一个数组时,要给编译器提供为数组分配内存所需的所有信息,包括值的类型
    和数组维,而值的类型决定了每个元素需要的字节数。
  • 数组维指定了元素的个数。
  • 数组占用的字节数是元素个数乘以每个元素的字节数。
  • 数组元素的地址是数组开始的地址,加上元素的索引值乘以数组中每个元索类型所需的字节数。

如下所示是数组变量保存在内存中的情形。

数组在内存中 的组织方式

  • 获取数组元素地址的方式类似于普通变量。对value 整数变量
  • 可以用以下语句输出它的地址:
    printf("数组value的地址是%p\n", &values);
  • 要输出number数组的第3个元素的地址,可以编写如下代码:
    printf("\n数组number的第三个元素的地址是%p%p\n\n", &number[2]);

3.2、输出数组的地址值

  • 下面的代码段设置了数组中的元素值,然后输出了每个元素的地址和内容。
int data[5];for (unsigned int i=0;i<5; ++i)data[i] = 12*(i + 1);printf ("data[&d] Address: 易p Contents: d\n", i, &data[i], data[i]) ;
  • for循环变量i遍历了data数组中的所有合法索引值。
  • 在这个循环中,位于索引位置i上的元素值设置为12*(i+1)。
  • 输出语句显示了当前的元素及其索引值,由i的当前值决定的数组元素的地址,以及存储在元素中的值。

上面的程序调试结果输出如下

数组value的地址是00CFF814数组number的第三个元素的地址是00CFF77400491023数组data[0] 的地址是: 00CFF750, 数组data[0]的数据是: 12数组data[1] 的地址是: 00CFF754, 数组data[1]的数据是: 24数组data[2] 的地址是: 00CFF758, 数组data[2]的数据是: 36数组data[3] 的地址是: 00CFF75C, 数组data[3]的数据是: 48数组data[4] 的地址是: 00CFF760, 数组data[4]的数据是: 60请按任意键继续. . .
  • i 的值显示在数组名后面的括号中。
  • 每个元素的地址都比前一个元素大4,所以每个元素占用4个字节。

四、确定数组的大小

4.1、sizeof运算符确定数组的大小

  • sizeof运算符可以计算出指定类型的变量所占用的字节数。
  • 对类型名称应用sizeof运算符。

如下:

   // 输出字节数    printf("long类型变量的大小为%zu 字节。\n", sizeof(long));
  • sizeof运算符后类型名称外的括号是必需的。

  • 如果漏了它,代码就不会编译。

  • 也可以对变量应用sizeof运算符,它会计算出该变量所占的字节数。

  • sizeof运算符生成size_ t类型的值,该类型取决于实现代码,一般是无符号的整数类型。

  • 如果给输出使用

%u
  • 说明符,编译器又把size_t定义为unsigned long或者unsigned long long,编译器就可能发出警告:使用%u说明符不匹配print()函数输出的值。
  • 使用%u会消除该警告消息。

4.2、sizeof运算符输出数组所占的字节数

  • sizeof运算符也可以用于数组。下面的语句声明一个数组:
double values[5] = ( 1.5, 2.53.54.55.5 };

可以用下面的语句输出这个数组所占的字节数:

// 输出数组字节数    printf("\n数组values的大小为%zu 字节。\n", sizeof(values));

调试结果输出如下

数组value的地址是00B3F7B0数组number的第三个元素的地址是00B3F71000631023数组data[0] 的地址是: 00B3F6EC, 数组data[0]的数据是: 12数组data[1] 的地址是: 00B3F6F0, 数组data[1]的数据是: 24数组data[2] 的地址是: 00B3F6F4, 数组data[2]的数据是: 36数组data[3] 的地址是: 00B3F6F8, 数组data[3]的数据是: 48数组data[4] 的地址是: 00B3F6FC, 数组data[4]的数据是: 60long类型变量的大小为4 字节。数组values的大小为40 字节。请按任意键继续. . .
  • 也可以用表达式
  • sizeof values[0]
  • 计算出数组中一个元素所占的字节数。
  • 这个表达式的值是8。当然,使用元素的合法索引值可以产生相同的结果。
  • 数组占用的内存是单个元素的字节数乘以元素个数。
  • 因此可以用sizeof运算符计算数组中元素的数目:
size_t element_count = sizeof values / sizeof values[0];
  • 执行这条语句后,变量element _count 就含有数组values中元素的数量。
  • element. count声明为size t 类型,因为它是sizeof运算符生成的类型。
  • 可以将sizeof运算符应用于数据类型,所以可以重写先前的语句,计算数组元素的数量。

如下所示

size_t elementCount = sizeof values / sizeof(double);
  • 这会得到与前面相同的结果,因为数组的类型是double, sizeof(double)会得到元素占用的字节数。
  • 有时偶尔会使用错误的类型,所以最好使用前一条语句。
  • sizeof运算符应用于变量时不需要使用括号,但一般还是使用它们。

4.3、sizeof运算符运用到for循环中

前面的例子可以编写为如下所示

double values[5] = { 1.5, 2.5,3.5, 4.5, 5.5 };size_t element_count = sizeof values / sizeof values[0];printf("\n数组values的大小为%zu 字节。\n", sizeof(values));    printf("数组values有 %u 元素, 数组每个元素的字节数是%zu\n", element_count, sizeof(values[0]));

这些语句的输出如下

数组value的地址是00EFFC1C数组number的第三个元素的地址是00EFFB7C00491023数组data[0] 的地址是: 00EFFB58, 数组data[0]的数据是: 12数组data[1] 的地址是: 00EFFB5C, 数组data[1]的数据是: 24数组data[2] 的地址是: 00EFFB60, 数组data[2]的数据是: 36数组data[3] 的地址是: 00EFFB64, 数组data[3]的数据是: 48数组data[4] 的地址是: 00EFFB68, 数组data[4]的数据是: 60long类型变量的大小为4 字节。数组values的大小为40 字节。数组values的大小为40 字节。数组values有 5 元素, 数组每个元素的字节数是8请按任意键继续. . .

在使用循环处理数组中的所有元素时,可以使用sizeof 运算符。

例如:

doub1e values[5] = { 1.5, 2.53.54.55.5 };double sum = 0.0;for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++)    {        sum += values[i];    }    printf("\n数组values中的这些值的和为 %.2f\n\n", sum); 

这些语句的调试结果输出如下

数组value的地址是00D3FE0C数组number的第三个元素的地址是00D3FD6C00211023数组data[0] 的地址是: 00D3FD48, 数组data[0]的数据是: 12数组data[1] 的地址是: 00D3FD4C, 数组data[1]的数据是: 24数组data[2] 的地址是: 00D3FD50, 数组data[2]的数据是: 36数组data[3] 的地址是: 00D3FD54, 数组data[3]的数据是: 48数组data[4] 的地址是: 00D3FD58, 数组data[4]的数据是: 60long类型变量的大小为4 字节。数组values的大小为40 字节。数组values的大小为40 字节。数组values有 5 元素, 数组每个元素的字节数是8数组values中的这些值的和为 17.50请按任意键继续. . .
  • 这个循环将数组中所有元素的值加起来。
  • 使用sizeof运算符计算数组中的元素个数,可以确保无论数组的大小如何,循环变量i的上限总是正确的。

五、完整程序

本文的完整程序如下所示

5.1 Main.h 文件程序

#pragma once#include #include 

5.2 Main.c 文件程序

#define _CRT_SECURE_NO_WARNINGS#include "Main.h"int main(){    system("color 3E");    // 定义数组    double values[5] = { 1.5, 2.5,3.5, 4.5, 5.5 };    double values1[5] = { 1.5, 2.5, 3.5 };    double values2[5] = { 0.0 };    int primes[] = { 2, 3,5, 7,11, 13, 17, 19,23, 291 };    long number[4];    int data[5];    double sum = 0;    // 数组数组的地址    printf("数组value的地址是%p\n", &values);    printf("\n数组number的第三个元素的地址是%p%p\n\n", &number[2]);    for (unsigned int i = 0; i < 5; ++i)    {        data[i] = 12 * (i + 1);        printf("数组data[%d] 的地址是: %p, 数组data[%d]的数据是: %d\n", i, &data[i], i, data[i]);    }    printf("\n");    // 输出字节数    printf("long类型变量的大小为%zu 字节。\n", sizeof(long));    // 输出数组字节数    printf("\n数组values的大小为%zu 字节。\n", sizeof(values));    size_t element_count = sizeof values / sizeof values[0];    size_t elementCount = sizeof values / sizeof(double);    /*double values[5] = { 1.5, 2.5,3.5, 4.5, 5.5 };    size_t element_count = sizeof values / sizeof values[0];*/    printf("\n数组values的大小为%zu 字节。\n", sizeof(values));    printf("数组values有 %u 元素, 数组每个元素的字节数是%zu\n", element_count, sizeof(values[0]));    for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++)    {        sum += values[i];    }    printf("\n数组values中的这些值的和为 %.2f\n\n", sum);     system("pause");    return 0;}

六、总结

本文主要介绍了C语言高级编程的数组的初始化的几种方法。
介绍了数组和地址之间的关系。
介绍了怎么样确定数组的大小。
介绍了sizeof怎么样确定数组大小。
通过实例程序来掌握C语言数组与地址的应用。

本文到这里就结束啦。
希望本文的C语言数组的初始化、数组和地址、确定数组的大小教程。
能对你有所帮助。