关于数组、结构体的初始化
一直以来,初始化变量和数组常采用定义时赋值的方法,今天在定义一个结构体的时候发现了一些问题,查了下相关资料发现以往的使用确实有些误区,一直没有注意到,于是搜集了下零散的资料在此记录一下。
一、以往常用的初始化方式:
1 int a=0; /*a初始化为0*/ 2 int b[10]={0}; /*b中全部元素初始化为0*/
想必一直这样使用也确实不会发现问题,按照惯性思维,把0换成1就是把全部元素初始化为1了!然而事实却并非如此,请看下面这段代码↓
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 int a=1; /*a初始化为1*/ 9 int b[10]={1}; /*b中全部元素被初始化为1?*/ 10 printf("a=%d\n",a); 11 for(a=0;a<10;a++) 12 { 13 printf("b[%d]=%d\n",a,b[a]); 14 } 15 return 0; 16 }
这段程序的输出结果如下↓
1 /* 2 a=1 3 b[0]=1 4 b[1]=0 5 b[2]=0 6 b[3]=0 7 b[4]=0 8 b[5]=0 9 b[6]=0 10 b[7]=0 11 b[8]=0 12 b[9]=0 13 Press any key to continue 14 */
可以看到,b数组中的元素只有b[0]被初始化为了1,其余元素依然为0。
通过查阅相关资料《The C++ Programming Language》,找到了以下内容:
5.2.1 数组初始化
数组可以用一个列值来初始化,例如
1 int v1[] ={1,2,3,4}; 2 char v2[]={'a','b','c',0};
当数组定义时没有指定大小,当初始化采用列表初始化了,那么数组的大小由初始化时列表元素个数决定。所以v1和v2分别为 int[4] 和char[4]类型。如果明确指定了数组大小,当在初始化时指定的元素个数超过这个大小就会产生错误!例如:
1 char v3[2] ={'a','b',0}; //错误:太多的初始化值了 2 char v3[3] ={'a','b',0}; //正确
如果初始化时指定的的元素个数比数组大小少,剩下的元素都回被初始化为 0 !
例如:
1 int v5[8]={1,2,3,4};
等价于
1 int v5[8]={1,2,3,4,0,0,0,0};
注意没有如下形式的数组赋值:
1 void f() 2 { 3 v4={'c','d',0}; //错误:不是数组赋值 4 }
如果你想这样的复制的话,请使用 vector(16章第三节) 或者 valarray(22章第四节)。
字符数组可以方便地采用字符串直接初始化(参考第五章 2.2小节)
译注: 就是 这样啦 char alpha []="abcdefghijklmn";
看完上述内容想必已经清楚的知道了数组应该怎样进行初始化了,此书在第六章还提及了结构体类型的的初始化问题,由于内容有过多重复,本文只列出重点。
二、集合的初始化
什么是 集合:顾名思义,集合(aggregate)就是多个事物聚集在一起,这个定义包括混合类型的集合:像struct和class等,数组就是单一类型的集合。
1、常见数组即为一种集合,此处做一个小总结:
1>为数组各个元素指定初值:
1 int a[5]={ 1, 2, 3, 4, 5};
2>如果给出的初始化值多于数组元素的个数,编译器就会给出一条出错信息。但如果给的初始化少于数据元素的个数,那将会怎么样呢?例如:
1 int b[6] = {0};
这时,编译器会把第一个初始化值赋给数组的第一个元素,然后用0赋给其余的元素。注意,如果定义了一个数组而没有给出一列初始值时,编译器并不会去做初始化工作。所以上面的表达式是将一个数组初始化为零的简洁方法,它不需要用一个for循环,也避免了“偏移1位”错误(它可能比for循环更有效,这取决于编译器)。
3>数组还有一种叫自动计数(automatic counting)的快速初始化方法,就是让编译器按初始化值的个数去决定数组的大小:
1 int c[ ] = { 1, 2, 3, 4 };
4>对于二维数组,可以看做多个一维数组组成的集合,使用用嵌套的大括号 {{a[0]},{a[1]},{a[2]},…,{a[n-1]}} 来初始化其中的每个一维数组,更高维数组也是如此。
1 int a[3][2]={{1,1},{2,3},{3,6}};
2.关于struct关键字:
在C语言中,struct作为结构体声明的关键字,不具备C++中类的功能,而在C++中,struct与class都可用做类关键字,区别在于struct类默认public,class类默认private,因此此处只介绍C语言中struct结构体的相关内容,C++中struct类可参考class部分。
因为结构也是一种集合类型,所以它们也可以用同样的方式初始化。
1>定义一个普通结构体类型X:
1 struct X 2 { 3 int i; 4 float f; 5 char c; 6 };
使用X创建对象时,可以这样初始化其每个成员的值:
1 X x1 = { 1, 2.2, 'c' };
使用X来创建对象数组时,可以用嵌套的大括号 {{obj 1},{obj 2},{obj 3},…,{obj n}} 来初始化每一个对象:
1 X x2[3] = { {1, 1.1, 'a'}, {2, 2.2, 'b'}};
这里只列出了两个对象的初值,所以第三个对象中的数据成员分别被初始化为对应数据类型的缺省初值①
2>对于包含数组的结构体来说,初始化与上述类似,需要说明的一点是,当数组成员在结构体中定义在首位且给出不完全初始化表的情况下,初值是按照 数组的元素顺序 + 之后的成员表 依次被赋初值的,此处举例说明:
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 struct Y 7 { 8 int i[2]; 9 float f; 10 char c; 11 }; 12 13 int main() 14 { 15 Y yy={1}; 16 Y y[3] = {1,2,3}; 17 printf("%d %d %f #%c#%d#\n", yy.i[0], yy.i[1], yy.f, yy.c, yy.c); 18 /*输出结果:1 0 0.000000 # #0# */ 19 printf("%d %d %f\n", y[0].i[0], y[0].i[1], y[0].f); 20 /*输出结果:1 2 3.000000 */ 21 printf("%d %f #%d#\n", y[2].i[0], y[2].f, y[2].c); 22 /*输出结果:0 0.000000 #0# */ 23 return 0; 24 }
对于更复杂结构体也是如此,用{}逐级表明赋值关系即可。
3.关于class类
C++最主要的类的使用还用说嘛!!!不会的自己去看课本,去看构造函数和静态成员的相关内容!!!╭(╯^╰)╮
三、补充
①各种数据类型的缺省初值表
1 数据类型 缺省初始化值 2 3 int 0 4 char '\0x0' 5 float 0.0 6 double 0.0 7 char Array[n] "" 8 int Array[n] {0,0,…,0}