表的大小不能超过数组的大小,另外对字符数组赋值时使用字符串形式时要比数组的容量至少小1,因为字符串有效内容的截止的最后一位必须是‘\\0’(NULL,就是空)。第三种是在声明的过程中对数组未指定大小,但是进行赋值。前两种想必你是用过的,而这第三种是通过编译器在编译的时候,通过测量赋值内容的大小,给数组进行大小分配空间。第三种赋值的好处就是你不必去查你赋值数据的个数,不用管有多少初始化的数据,直接用这样的方式就可以了,而且不必担心内存的浪费。
这样的赋值方式同样适用于char float double等数据类型。可以照搬使用。
下面简要介绍一下数组的特点。数组的第一个是0号第二个是1号,也就是说数组array的第一
个元素是a[0],第二个才是a[1]。因为数电就是这样,0是起始位,记住就好。
所以一个大小为n的数组最后一个元素是a[n-1],上例中array[10]数组的最后一位是array[9]。 既然讲到了这里,那么顺便讲一下数组越界。在计算机中,越界是一个很严重的问题,因为越界
的时候程序会读取或更改不属于这个数组的数据,而使程序出错。越界很简单,代码如下:
#include
char b[10]={0,1,2,3,4,5,6,7,8,9}; int a[10]={0,1,2,3,4,5,6,7,8,9}; for(int i=0;i<20;i++) printf(\ system(\
}
这是一个很简单的程序,执行效果如下:
输出结果是惨不忍睹的,如果换成%d输出,那么你会看到不一样的结果:
可以看到前面的输出还算正常,但是后面的输出就未能如愿输出了,这就是越界的后果。输出越界只不过是看到乱码,或者访问权限问题。如果是赋值越界,那么你的程序很可能崩溃掉。比如这样修改后:
#include
{
char b[10]={0,1,2,3,4,5,6,7,8,9}; int a[10]={0,1,2,3,4,5,6,7,8,9}; for(int i=0;i<1000;i++)
}
a[i]=5;
system(\
上面的程序执行后就是一闪而过,因为system函数的代码已经被上面的赋值语句破坏了,所以无法执行。
关于越界问题还有一个需要注意的是越界属于逻辑错误,而不是语法错误,所以不要指望编译器
为你指出这个错误。在这个问题上,编译器做的确实不怎么样,全靠程序员自己。另外需要注意的是初始化列表越界是会被编译器检查出来的,前面有讲到。
越界问题到此告一段落。
在使用和特性上,整形和浮点基本没什么本质差别,一样用就行了。 字符数组的特点
字符数组在赋值的时候有两种选择方式。第一种是像常规的赋值方式一样,就是使用简单的前面
讲的3种方法,在这里就不再重复了。另外一种方法是以字符串的形式对数组进行赋值,这种赋值方式有一定的好处,这个前面提过,但是不详细。赋值方式是这样的:array[10]=”012345678”;,这里最后一位是NULL,编译器自己加的,所以有效的元素是前9个就是array[0]->array[8]。而array[9]的值是NULL。有必要介绍一下NULL是一个在标准定义文件中的宏定义,其值就是0,转
换成二进制就是0000 0000,其转义字符就是‘\\0’,从下面的代码中你可以看出来:
你可以看到,我给a[0]的赋值是‘\\0’,而其输出也是0。a[1]的值是NULL输出也是零。再看下面的修改结果:
我在第一行中给b[10]数组赋了9个值,其输出是按照10个来的。可以看到,初始化列表中我没有进行处理的a[9]是有值的,是0值,也就是NULL和‘\\0‘,这三者等价。
当然,如果你对数组进行赋值时没有这么精打细算,比如一个大小为10个元素的你只用字符串
方式赋了小于9个元素的值,那么未赋值的元素位置的值也是0.就是下面这样:
明白了没? 另外需要强调的是如果你使用常规方式对字符数组进行赋值,在上述的未全部赋值的情况下,效果是一样的,后面的值也将全部为0。但是却没有了最后一位必须为0的字符串特有的限制,也就是说
a[10]=”0123456789”; //非法 因为是字符串,多了最后的9
a[10]= {'0','1','2','3','4','5','6','7','8','9'};//合法 因为这是字符数组,没有最后一位必须为0
的限制。
一维数组的赋值就讲到这里,下面的内容是一维指针。
指针是C语言中固有的一种数据类型,其本质就是一个存有地址的变量。如果你想看看一个指针
的值是多少,大可用printf函数去用%d的格式去输出他。下面这段简单的代码就是做到了这一点
这里随机定义了一个整型指针,其值是2。能随机出现这个数是在不易,可能是因为我之前调试
了几个小程序吧。所以现在你能知道其含义了吧,就是地址的值。
计算机内存的地址是用从0至某一个数来表示的,在这个数之后是其他的一些用途的地址,比如
硬盘,BIOS的地址。每一个编号对应的是1B,就是一个字节。这些之前讲过,你可以看一看。一个字节能存储一个ACS码,最大数字是255。通过前面你可以知道,指针存储的值就是一个存有内存编号的整型变量。通过*符号来实现对指针指向地址的内容的访问。如果你现在想输出指针a的值,那么*a就是了。示例如下:
这里你可以看到,系统出现了错误提示。这里就是因为内存0x00000002不是这个程序可以读取
的。这样的提示想必你以前也看到过,注意就是了,指针指向的内容不是你可以随便处理的,只有系统给你提供的内存才能供你使用,否则是非法的。刚才讲的有点歪。
上图中你可以看到之前值为2的a在成为*a后就变成了编号为0x00000002内存。现在你应该
知道指针是怎么使用的了吧。简言之就是没有*时是指针本体,有了*号就是指针的指向。所以指针这个名字起的非常好。
另外简介一下而为指针,其实而为指针这可理解为指向指针的指针,声明方式就是在其前面用**
声明。形式时
类型 **变量名;
其形式还是很简单的。需要注意的是,当你使用 *变量名时 ,其含义是指向一个维指针的指针。听起来可能有些别扭,但是就是这么一回事。这种而为指针我用的比较少,基本都是变相使用二维指针,相对于一维指针,而为指针考得比较少,所以不用太过深究,没用。下面的这个小程序很简明的显示了其工作原理:
相信你看过之后很容易就理解了。
二维数组也不用说太多,大致介绍一下二维数组行和列的关系接可以了。二维数组的声明形式是:
类型 变量名[ ][ ];
这里第一个方框是行大小控制,第二个方框是列大小控制。比如我要声明一个3行4列的整型数组,那么就可以这样声明:
int array[3][4];
通常在赋值的时候,可以用for循环对数组进行赋值,对于这个数组,可以用这样的语句进行赋
值: