所有C语言数组和指针的知识都在这里了!|周立功手把手教你学C语言编程
;
5 int b = &data;
6 return 0;
7 }
通过编译器提示的警告,"'int' differ in levels of indirection from 'int (*)[3]'",说明&data的类型为int (*)[3]。
(4)sizeof(data)
当data作为sizeof的操作数时,其返回的是整个数组的长度。在这里,sizeof(data)的大小为12,即3个元素占用的字节数为4×3=12,系统会认为&data+1中的"1",偏移了一个数组的大小,因此&data +1是下一个未知的存储空间的地址(即越界)。在小端模式下,数组在内存中的存储方式详见图 1.10。
图 1.10 数组的存储
将如何寻找相应的数组元素呢?常用的方法是通过"数组的基地址+偏移量"算出数组元素的地址。在这里,第一个元素&data[0]的地址称为基地址,其偏移量就是下标值和每个元素的大小sizeof(int)相乘。假设数组元素&data[0] 的地址为A,且在内存中的实际地址为0x22FF74,那么&data[1]的值为:
A + 1×sizeof(int) = (unsigned int)data + 4 = 0x22FF74 + 4 = 0x22FF78
&data[2]的值为:
A + 2×sizeof(int) = (unsigned int)data + 8 = 0x22FF74 + 8 = 0x22FF7C
实际上,当在C语言中书写data[i]时,C将它翻译为一个指向int的指针。Data是指向data[0]的指针,data+i是指向data[i]的,因此不管data数组是什么类型,总有data+i等于data[i],于是*(data+i)等于data[i],其相应的测试范例程序详见程序清单 1.22。
程序清单 1.22 变量的地址测试程序
1 #include
2 int main(int argc, char *argv[])
3 {
4 int data[3] = {1, 2, 3};
5 printf("%x, %x, %x, %x, %x", &data[0], &data[1], &data[2], &data, &data+1);
6 return 0;
7 }
实践证明,虽然&data[0]与&data的类型不一样,但它们的值相等。同时也可以看出,数组的元素是连续存储的。如果将数组变量占用内存的大小除以数组变量中一个元素所占用空间的大小,便可得到数组元素的个数。即:
int numData = sizeof(data) / sizeof(data[0]);
当然,也可以使用宏定义计算数组元素的个数:
#define NELEMS(data) (sizeof(data) / sizeof(data[0])
当数组作为函数的参数时,C语言函数的所有参数必须在函数内部声明。但是,由于在函数内部并没有给数组分配新的存储空间,因此一维数组的容量只在主程序中定义。显然,如果函数需要得到一维数组的大小,则必须将它以函数参数的形式传入函数中,或将它作为全局变量访问。
- 程序设计基础:字符能像整数一样计算(07-29)
- 周立功教你学C语言编程:教你数组是如何保存指针的(07-31)
- 周立功《程序设计与数据结构》:字符串函数(08-05)
- 周立功手把手教你学C语言编程:用数组,构造一个双重指针(08-04)
- 周立功教你学程序设计结构体:内存对齐和基本数据类型(08-01)
- 跟周立功学C语言编程:如何将二维数组作为函数参数传递?这三要素要时刻谨记!(08-06)