【C基础】08 数组

一、一维数组

1、定义

定义格式类型 变量名称[元素数量] ;
例如:int grades[100] ;double weight[20] ;

说明

  • 元素数量也即是数组长度;
  • 数组长度必须是整数,在编译时必须是确定的字面量(C99之前)。C99之后,可以是任何(整数)常量表达式,为了便于调整数组长度,可用宏定义数组长度。
  • 数组定义后,再次调用整个数组,不需要写[],直接用数组名即可代表整个数组。例如:sizeof(a);(求数组a占用的字节数)

数组特点

  • 数组是一个容器,其内部所有元素具有相同的数据类型;
  • 一旦创建,不能改变大小;
  • 数组中的元素在内存中是紧密依次排列的

int a[10]为例:

  • 一个int型数组;
  • 共10个单元:a[0], a[1], a[2], … a[9],依次紧密排列;
    请添加图片描述
  • 可以出现在赋值=的左边(左值)或右边,例如:a[2] = a[1]+6;

2、数组下标

定义
  使用数组时,放在[]内的数字称为下标索引数组下标从0开始。长度为n的数组元素的下标是0 ~ n-1

  • 数组下标可以是任何整数表达式,如a[i + j*10] = 0;a[i++] = 0;
  • 无论读写,编译器不会检查数组下标是否越界。越界数组访问可能导致程序崩溃(segmentation fault)。只能考程序员写代码时保证不越界。

举例int a[10];程序中出现对a[10]的读写都是越界了(有效下标为0 ~ 9)。

  • 长度为0的数组可以存在,但是无用。

举例:

//统计0~9数字个数
const int number = 10;    //定义数组长度
int x,i;
int count[number] = {
   0};  //数组定义和初始化
scanf("%d",&x);
while(x != -1){
   
	count[x]++;
	scanf("%d",&x);
}
//遍历数组输出
for(i=0;i<number;i++){
   
	printf("%d:%d次\n",i,count[i]);
}

3、数组 初始化

(1) 格式

数组类型 数组名称[数组长度] = {整型常量表达式列表};

例如:int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} ;

(2) 说明

  • 用花括号{}括起来的整型常量表达式列表称为数组初始化器
  • 若初始化器比数组短,则剩余元素默认为0。例如:
    int a[10] = {1, 2, 3, 4, 5, 6} ;等价于int a[10] = {1, 2, 3, 4, 5, 6, 0, 0, 0, 0} ;
  • 全0初始化:int a[10] = {0} ;
  • 注意int a[10] = {2} ;等价于int a[10] = {2, 0, 0, 0, 0, 0, 0, 0, 0, 0} ;。全0初始化为特殊情况,其他值并不适用。且仅适用于数组定义时的初始化,例如:
	int a[10] = {
   0};  //合法初始化
	
	int b[10];
	b[10] = {
   0};     //非法赋值
  • 初始化器为空是非法的。
  • 初始化器必须不长于数组长度,否则也非法。
数组的集成初始化
  • 若给定初始化器,可省略数组长度。编译器用初始化器的长度来确定数组大小。例如:
    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} ;
  • 花括号后面的分号;不能漏掉,这与块不同。

(3) 常见的初始化

① 初始化器比数组短

若初始化器比数组短,则剩余元素默认为0。例如:
int a[10] = {1, 2, 3, 4, 5, 6} ;等价于int a[10] = {1, 2, 3, 4, 5, 6, 0, 0, 0, 0} ;

② 全0初始化

格式:int a[10] = {0} ;

注意int a[10] = {2} ;等价于int a[10] = {2, 0, 0, 0, 0, 0, 0, 0, 0, 0} ;。全0初始化为特殊情况,其他值并不适用。

③ 定位初始化(数组指示器)
  • [i]和整型常量表达式一起组成一个指示器,用[i]在初始化数据中给出定位;
  • 没有定位的数据接在前面相邻有定位元素后面;
  • 其余位置补0;
    也可以不给出数组长度,让编译器算;
    适合初始化数据特别稀疏的数组;

例如:

  • int a[10] = { [0] = 2, [2] = 3, 6} ;等价于int a[10] = { 2, 0, 3, 6, 0, 0, 0, 0, 0, 0} ;
  • int a[] = { [0] = 2, [2] = 3, 6} ;等价于int a[4] = { 2, 0, 3, 6} ;

不要求赋值顺序:

  • int a[10] = {[2] = 3, [0] = 2 , 6} ;等价于int a[10] = { 2, 0, 3, 6, 0, 0, 0, 0, 0, 0} ;

4、求数组长度sizeof

  • 求数组长度sizeof(数组名)/sizeof(a[0]) ; 即:数组长度 = 整个数组所占字节数/单个元素所占字节数。例如:sizeof(a)/sizeof(a[0]) ;
  • sizeof使用的格式说明选取%lu(unsigned longC89中最大的无符号整型)。C99中可使用更长的%zu。
    例如:
#define SIZE sizeof(a)/sizeof(a[0])

int main(void){
   
	
	int a[] = {
   4,9,1,8,[0]=5,7};
	int i;
	
	printf("sizeof(a[]) = %lu\n",SIZE);
	for(i=0; i<SIZE; i++) {
   
		printf("%d ",a[i]);
	}
	
	return 0;
}

显示结果为:
请添加图片描述
注意:数组a长度为4,不是6。编译器默认用’4’, ‘9’, ‘1’, '8’初始化元素0~3,遇到指示器后用’5’初始化元素0,紧随其后的’7’初始化元素1,结束。

5、其他

  • 一个数组不能直接对另一个数组整体赋值。例如
	int a[5] = {
   1, 2, 3, 4, 5};
	int b[5] = a;   //非法赋值
  • 数组变量本身不能被赋值;
  • 要把一个数组的所有元素交给另一个数组,必须采用遍历。
  • 遍历数组时通常使用for循环。

对数组整体赋值(遍历):

for(i=0; i<length; i++){
   
	b[i] = a[i];
}
  • 遍历数组的常见错误:

    • 从0开始,则应以<数组长度结束,而非<=;
    • 离开循环之后,继续用i的值表示数组元素下标。此时i=数组长度,但越界(0~n-1)。
  • 对数组整体赋值,除了逐个遍历之外,还可使用<string.h>头的memcpy函数,特别是处理大型数组时,速度更快。例如:

#include <string.h>  //调用此header中的memcpy函数

int main(void){
   
	
	int a[] = {
   0,1,2,3,4,5,6};
	int b[7];
	int i;
	memcpy( b, a, sizeof(b) );  //把数组a中的元素复制到b中  
	printf("b[10] = {")
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值