“数组下标应该从0开始还是1开始?我提出的折中方案0.5被拒绝了,而且我想,没有得到应有的认真考虑。”
——斯坦·凯利-布特尔(Stan Kelly-Bootle),计算机科学家
幸运的是,C语言有数组。我的意思是,我知道它被认为是一种低级语言,但它至少内置了数组的概念。由于很多语言的设计都从C语言的语法中获得灵感,你也许已经熟悉用方括号 [] 来声明和使用数组了。
但是C语言几乎只是“表面上”有数组!正如我们稍后会发现,数组实际上只是语法糖——它们本质上都是指针和底层的东西。别慌!但目前,我们就先把它们当作数组来用吧。呼。
我们来举个例子:
#include <stdio.h>
int main(void)
{
int i;
float f[4]; // 声明一个包含4个浮点数的数组
f[0] = 3.14159; // 下标从0开始,当然啦
f[1] = 1.41421;
f[2] = 1.61803;
f[3] = 2.71828;
// 打印所有元素:
for (i = 0; i < 4; i++) {
printf("%f\\n", f[i]);
}
}
声明数组时,必须指定它的大小,并且这个大小必须是固定的。
在上面的例子里,我们创建了一个包含4个浮点数的数组。声明时方括号中的数字就是数组的大小。
后续代码中,我们通过方括号访问数组里的值,可以给它们赋值,也可以读取它们。
希望这对你来说看起来很熟悉,因为你可能已经接触过类似的语言了!
你不能完全做到这一点。C语言不会记录这个信息。你必须在另一个变量中单独管理它。
当我说“不能”时,我实际上是指有些情况下你是可以的。有一种技巧可以在数组声明的作用域内得到数组元素的数量。但一般来说,这在你把数组传递给函数时不起作用。
我们来看一下这个技巧。基本思路是先用 sizeof 取数组的总大小,然后除以每个元素的大小,就能得到数组的长度。例如,如果一个 int 是4字节,数组总长度是32字节,那么数组中必然有 32 ÷ 4 = 8 个 int。
int x[12]; // 12个int
printf("%zu\\n", sizeof x); // 48字节总大小
printf("%zu\\n", sizeof(int)); // 每个int 4字节
printf("%zu\\n", sizeof x / sizeof(int)); // 48/4 = 12个int!
如果是字符数组,那么 sizeof 数组的值就是元素个数,因为 sizeof(char) 被定义为1。对于其他类型,你需要除以每个元素的大小。
但这个技巧只在数组被定义的作用域内有效。如果你把数组传递给函数,它就不起作用。即使你在函数参数中写成“很大”的形式:
void foo(int x[12])
{
printf("%zu\\n", sizeof x); // 8?48去哪了?
printf("%zu\\n", sizeof(int)); // 每个int 4字节
printf("%zu\\n", sizeof x / sizeof(int)); // 8/4 = 2个int??错了。
}
这是因为,当你“传递”数组给函数时,实际上传递的只是指向第一个元素的指针,而 sizeof 测量的就是这个指针的大小。关于这个内容,可以参考下面“将一维数组传递给函数”一节。