最近看到一些别人的代码,对结构体的初始化使用了不同的语法,就决定对结构体的初始化方法做个探索,这里小小的记录一下。
注意,没有初始化的结构体变量是不会输出的,比如
struct SBase{int iNumberOne;int iNumberTwo;long double ldNumberThree;int gNumber[5];int *pNumber;
}
SBase sBase;
cout<
这样会报错,因为编译器无法确定变量的值;
定义一个结构体,第一种初始化结构体的方法
struct SBase{int iNumberOne;int iNumberTwo;long double ldNumberThree;int gNumber[5];int *pNumber;
}
SBase sBase = {1,2}; //结构体会按照顺序编译,因此,第一个变量iNumberOne初始化为1,第二个变量iNumberTwo初始化为1后面所有的变量初始化为0,也包括指针变量pNumber也被赋值为0;
cout< cout<
这种方法是定义结构体时没有初始化,在定义结构体对象的时候,才使对象内的数据变量初始化。因此不同的对象初始化数据不同。
当结构体内嵌套结构体时,此方法是如何初始化的呢?
struct A
{int iNumber1;int iNumber2;
}
struct B
{A a;int iNumeber3;
}
B b = {2};
cout<
这种的思路是首先对于对象b而言,a被初始化为2,iNumber3默认为0,而A a ={2},再回到a对象中,iNumber1初始化为2,iNumber2没有指定,默认为0;
struct SBase{int iNumberOne;int iNumberTwo;long double ldNumberThree;int gNumber[5];int *pNumber;SBase(){iNumberOne = 1;iNumberTwo = 2;ldNumberThree = 3.0;for(int i = 0; i < 5;i++){gNumber[i] = 0;}pNumber = NULL;}
}
SBase sBase;
cout<
这种方法跟类变量初始化一样,采用的是构造函数,这样便可以在定义结构体的时候便已经赋予了初始化值。这样定义结构体对象的时候就可以不赋予初始值了;
struct SBase{int iNumberOne;int iNumberTwo;long double ldNumberThree;int gNumber[5];int *pNumber;
}
SBase sBase;
memset(&sBase,0,sizeof(SBase));
cout<
这样采用memset的方法,可以将多个变量用一行代码置0,缺点是所有变量的数值一样;但是
memset(&sBase,1,sizeof(SBase));
cout<
这种方法不代表将所有的变量置1,会将所有的变量赋予乱值;
结构体内元素是连续排列的,但是地址需要满足字节对齐。
什么是字节对齐呢?下面给个例子展示一下。
struct SBase{int iNumberOne;char chNumberTwo;double dNumberThree;int iNumberFour;
}
SBase sBase = {1};
cout<<"内存排列是:"<< &sBase.iNumberOne<< " "<< (int *)&sBase.chNumberTwo << " "<<&sBase.dNumberThree << " "<<&sBase.iNumberFour<
最终显示的结果是
内存排列是:001BF5D8 001BF5DC 001BF5E0 001BF5E8
这里内存排列虽然是连续的,但是char字符占1一个字节,为什么内存地址5DC后面是5E0,差了4个字节?,这里就是因为计算机系统里内存的排列顺序是按照字节对齐的原则排布的。
int占4个字节,其地址应该是4的倍数,同理,char地址是1的倍数,double地址是8的倍数,这里char后面若紧跟double类型,double地址就不是8的倍数了,因此在char后面补了3个0,最终内存排布如图所示。