数组
基本的程序结构
第一种结构就是顺序结构,它指的是我们所写的按照顺序执行的代码,执行完上一行,再执行下一行这种的。第二种就是分支结构,主要是用 if 条件分支语句来实现,主要特征是根据表达式的真假,选择性地执行后续代码。最后一种就是循环结构,用来重复执行某段代码的结构。
例题:请输出 1 到 7 的每一个数字二进制表示中的 1 的个数
数字 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
二进制 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
int cnt = 0;
while (n != 0) {
if (n % 2 == 1) cnt += 1;
n /= 2;
}
什么是数组?
所谓数组,你可以把这两个字对调过来理解,即组数,一组数据。
int arr[1000];
这里相当于向计算机申请了可以存储 1000 个整型变量的存储空间。第一个存储整型数据的内存空间,也就是第一个整型变量,就是 arr[0],第二个整型变量是 arr[1],以此类推。arr 后面方括号里面的东西,我们称之为“数组下标”,数组下标从 0 开始,也就是说,代表 1000 个整型变量的数组,下标范围应该是 0 到 999。
字节与地址
什么是字节呢?它是计算机中最基本的存储单位,就像一个一个不可分割的小格子一样,存在于我们计算机的内存中。例如,我们通常所说的,一个 32 位整型元素占用 4 个字节,那就意味着这个元素需要占用 4 个小格子,不会存在某个元素占用 0.5 个小格子的情况。这就是所谓的不可分割。
sizeof 的使用,就像函数方法一样,我们想要查看什么元素或者类型所占用字节数量,就把什么传入 sizeof 即可,就可以查看某个元素占多大的存储空间。
字节是存储数据的最基本单位,比特是表示信息的最基本单位。
CPU 能够准确找到程序所需要数据的本质原因,也是因为每一个字节都有一个独立的编号,我们管这个编号,叫做:内存地址!
内存地址
不同数据类型,用不同的格式占位符输出,例如:%d 对应了十进制整型的输出。内存地址则采用 %p 这个格式占位符进行输出,下面给你一个演示程序,你可以在你的环境中运行一下:
#include <stdio.h>
int main() {
int a;
printf("%p\n", &a); // 输出 a 变量的地址
return 0;
}
-
第一,数组的每个元素之间在内存中是连续存储的,也就是对上面程序中的数组而言,第一个元素占头 4 个字节,第二个元素紧接着占接下来的 4 个字节的存储空间。再结合上面说到的变量首地址的概念,你就很容易理解为什么头两个地址之间差 4 了。
-
第二,在程序中,当我们单独使用数组名字的时候,实际上就代表了整个数组的首地址,整个数组(arr[100])的首地址就是数组中第一个元素的首地址,也就是 arr[0] 的地址。
思考题:去掉倍数
设计一个去掉倍数的程序,要求如下:
首先读入两个数字 n 和 m,n 的大小不会超过 10,m 的大小都不会超过 10000;
接下来读入 n 个各不相同的正整数,输出 1 到 m 中,有哪些数字无法被这 n 个正整数中任意的一个整除。
输入如下:
3 12
4 5 6
输出如下:
1 2 3 7 9 11
代码如下
#include <stdio.h>
int main() {
int m,n;
int a[10000];
int i,j;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(i=1;i<=m;i++)
{
for(j=0;j<n;j++)
{
if(i%a[j]==0)
{
break;
}
else if(j==n-1)
{
printf("%d",i);
}
}
}
return 0;
}
总结
- 使用数组,可以很方便的定义出一组变量存储空间,数组下标从 0 开始。
- 数据的最基本存储单位是字节,每一个字节都有一个独一无二的地址。
- 一个变量占用若干个字节,第一个字节的地址,是这个变量的首地址,称为:变量地址。