所有C语言数组和指针的知识都在这里了!|周立功手把手教你学C语言编程
因为标准C认为数组元素的个数n不是常量,虽然编译器似乎已经"看到"了n的值,但int array[n]要在运行时才能读取变量n的值,所以在编译期无法确定其空间大小。使用符号常量定义数组长度的正确形式如下:
#define N 10
int array[N];
即可根据实际的需要修改常量N的值。
由于数组元素下标的有效范围为0~N-1,因此data[N]是不存在的,但C语言并不检查下标是否越界。如果访问了数组末端之后的元素,访问的就是与数组不相关的内存。它不是数组的一部分,使用它肯定会出问题。C为何允许这种情况发生呢?这要归功于C信任程序员,因为不检查越界可以使运行速度更快,所以编译器没有必要检查所有的下标错误。因为在程序运行之前,数组的下标可能尚未确定,所以为了安全起见,编译器必须在运行时添加额外代码检查数组的每个下标值,但这样会降低程序的运行速度。C相信程序员能编写正确的代码,这样的程序运行速度更快。但并不是所有的程序员都能做到这一点,越界恰恰是初学者最容易犯的错误,因此要特别注意下标的范围不能超出合理的界限。
(3)变量的地址与类型
当将变量data[0]、data[1]和data[2]作为&的操作数时,&data[0]是指向变量data[0]的指针,&data[1]是指向变量data[1]的指针,&data[2]是指向变量data[2]的指针。data[0]、data[1]和data[2]变量的类型为int,&data[0]、&data[1]和&data[2]指针的类型为int *const,即指向常量的指针,简称常量指针,其指向的值不可修改。比如:
int a;
int * const ptr = &a;
ptr = NULL; // 试图修改,则编译报警
&a = NULL; // 试图修改,则编译报警
同理,&data是指向变量data的指针,那么data是什么类型?
按照声明变量的规约,将标识符data取出后,剩下的"int [3]"就是data的类型,通常将其解释为由3个int组成的数组类型,简称数组类型。其目的是告诉编译器需要分配多少内存?3个元素的整数数组,data类型测试程序详见程序清单 1.20。
程序清单 1.20 data类型测试程序
1 #include
2
3 void f(int x);
4 int main(int argc, char *argv[])
5 {
6 int data[3];
7 f(data);
8 return 0;
9 }
通过编译器提示的警告,"funtion: 'int' differ in levels of indirection from 'int [3]'",说明数组变量data的类型为不是int而是int [3]数组类型。由于在设计C语言时,过多地考虑了开发编译器的便利。虽然设计编译器更方便了,却因为概念的模糊给初学者造成了理解上的困难。实际上数组应该这样定义:
int [3] data;
即int是与[3]结合的。&data到底是什么类型?
当data作为&的操作数时,则&data是指向data的指针。由于data的类型为int [3],因此&data是指向"int [3]数组类型"变量data的指针,简称数组指针。其类型为int (*)[3],即指向int [2]的指针类型。为何要用"()"将"*"括起来?
如果不用括号将星号括起来,那么"int (*)[3]"就变成了"int *[3]",而int *[3]类型名为指向int的指针的数组(元素个数3)类型,这是设计编译器时约定的语法规则。
&data的类型到底是不是"int (*)[3]"?其验证程序范例详见程序清单 1.21。
程序清单 1.21 &data类型测试程序
1 #include
2 int main(int argc, char *argv[])
3 {
4 int data[3]
- 程序设计基础:字符能像整数一样计算(07-29)
- 周立功教你学C语言编程:教你数组是如何保存指针的(07-31)
- 周立功《程序设计与数据结构》:字符串函数(08-05)
- 周立功手把手教你学C语言编程:用数组,构造一个双重指针(08-04)
- 周立功教你学程序设计结构体:内存对齐和基本数据类型(08-01)
- 跟周立功学C语言编程:如何将二维数组作为函数参数传递?这三要素要时刻谨记!(08-06)