本节书摘来自异步社区《指针的编程艺术(第二版)》一书中的第1章,第1.2节,作者 蔡明志,更多章节内容可以访问云栖社区“异步社区”公众号查看
1.2 一维数组
指针的编程艺术(第二版)
我们把焦点转到一维数组,范例addressArray-5展示了如何调用scanf函数,并从键盘向数组输入数据。
范例addressArray-5
/* addressArray-5.c */
include <stdio.h>
include <conio.h>
int main()
{
int x[5];
int i;
for(i=0; i<5; i++)
{
printf("请输入x[%d]的整数值: ", i);
scanf("%d", &x[i]);
}
for(i=0; i<5; i++)
printf("x[%d] = %d\n", i, x[i]);
printf("\n");
for(i=0; i<5; i++)
{
printf("请输入x[%d]的整数值: ", i);
scanf("%d", x+i);
}
for(i=0; i<5; i++)
printf("x[%d] = %d\n", i, x[i]);
printf("\n");
getch();
return 0;
}
输出结果
这个数组有5个元素,分别为x[0]、x[1]、x[2]、x[3]和x[4]。每一个元素都是整数变量,所以只要在这些变量前加上&,即表示该变量在内存的地址。程序使用循环方法,输入数据给x数组,如下所示:
`
javascript
for(i=0; i<5; i++)
{
printf("请输入x[%d]的整数值: ", i);
scanf("%d", &x[i]);
}
这是最典型的做法。由于数组的名称表示该数组第一个元素的地址,也就是x等同于&x[0],x+1等同于&x[1],…,依此类推。所以也可以用下列方式来表示:
```javascript
for(i=0; i<5; i++)
{
printf("请输入x[%d]的整数值: ", i);
scanf("%d", x+i);
}
请不要在已表示数组名前又加上&,如该示例中的x数组,因为x已表示地址,所以再加上&,等于画蛇添足。
我们也可以在定义数组时顺便指定初始值,如下例所示。
int x[5] = {10, 20, 30, 40, 50};
表示数组有五个元素,分别为x[0]、x[1]、x[2]、x[3]、x[4],其所对应的内存地址,表示为&x[0]、&x[1]、&x[2]、&x[3]、&x[4]或x、x+1、x+2、x+3、x+4。如果想知道数组中的每一个元素所在的内存地址,可利用%p或%x的对应格式。请参阅范例addressArray-10。
范例addressArray-10
/* addressArray-10.c */
include <stdio.h>
include <conio.h>
int main()
{
int x[5] = {10, 20, 30, 40, 50};
int i;
for(i=0; i<5; i++)
printf("&x[%d] = %p\n", i, &x[i]);
printf("\n");
for(i=0; i<5; i++)
printf("x+%d = %p\n", i, x+i);
printf("\n");
for(i=0; i<5; i++)
printf("x[%d] = %d\n", i, x[i]);
getch();
return 0;
}
输出结果
由于这个数组的数据类型是int,所以元素之间的地址相隔4字节。当x等于0012FF4C,x+1是0012FF50。要注意这里的1,是表示每一单位所占的字节(bytes)数,就此数组而言,x+1等于0012FF4C + (1*4),由此得到0012FF50。如下图所示。
若将数据类型改为double,则情形又会如何?请参阅范例addressArray-15。
范例addressArray-15
/* addressArray-15.c */
include <stdio.h>
include <conio.h>
int main()
{
double x[5] = {10.1, 20.2, 30.3, 40.4, 50.5};
int i;
for(i=0; i<5; i++)
printf("&x[%d] = %p\n", i, &x[i]);
printf("\n");
for(i=0; i<5; i++)
printf("x[%d] = %\n", i, x[i]);
getch();
return 0;
}
输出结果
由于此范例的数组数据类型为double,所以元素之间的地址相隔8字节。