数组,结构体初始化{0}
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数组,结构体初始化{0}
一直以为int a[256]={0};是把a的所有元素初始化为0,int a[256]={1};是把a所有的元素初始化为1.
调试的时查看内存发现不是那么一回事,翻了一下《The C++ Programming Language》总算有定论。
PDF的竟然不然复制,就把它这章翻译了,如下
5.2.1 数组初始化
数组可以用一个列值来初始化,例如
int v1[] ={1,2,3,4};
char v2[]={'a','b','c',0};
当数组定义时没有指定大小,当初始化采用列表初始化了,那么数组的大小由初始化时列表元素个数决定。
所以v1和v2分别为 int[4] 和char[4]类型。
如果明确指定了数组大小,当在初始化时指定的元素个数超过这个大小就会产生错误。
例如:
char v3[2] ={'a','b',0}; //错误:太多的初始化值了
char v3[3] ={'a','b',0}; //正确
如果初始化时指定的的元素个数比数组大小少,剩下的元素都回被初始化为 0。
例如
int v5[8]={1,2,3,4};
等价于
int v5[8]={1,2,3,4,0,0,0,0};
注意没有如下形式的数组赋值:
void f()
{
v4={'c','d',0}; //错误:不是数组赋值
}
如果你想这样的复制的话,请使用vector(16章第三节) 或者valarray(22章第四节)。
字符数组可以方便地采用字符串直接初始化(参考第五章 2.2小节)
译注:就是这样啦 char alpha []="abcdefghijklmn";
The C++ Programming Language ,Third Edition by Bjarne Stroustrup.
、、、、、、、、、、、、、、、、、、、、、、、、、、、///////
/////////////////////////////////////////////////////////////
6.6 集合初始化
顾名思义,集合(aggregate)就是多个事物聚集在一起,这个定义包括混合类型的集合:像struct和class等,数组就是单一类型的集合。
初始化集合往往既冗长又容易出错,而C++中集合初始化(aggregate initialization)却变得很方便而且很安全。
当产生一个集合对象时,要做的只是指定初始值就行了,然后初始化工作就由编译器去承担了。
这种指定可以用几种不同的风格,它取决于正在处理的集合类型。
但不管是哪种情况,指定的初值都要用大括号括起来。
比如一个内部类型的数组可以这样定义:
int a[5] = { 1, 2, 3, 4, 5 };
如果给出的初始化值多于数组元素的个数,编译器就会给出一条出错信息。
但如果给的初始化少于数据元素的个数,那将会怎么样呢?例如:
int b[6] = {0};
这时,编译器会把第一个初始化值赋给数组的第一个元素,然后用0赋给其余的元素。
注意,如果定义了一个数组而没有给出一列初始值时,编译器并不会去做初始化工作。
所以上面的表达式是将一个数组初始化为零的简洁方法,它不需要用一个for循环,也避免了“偏移1位”错误(它可能比for循环更有效,这取决于编译器)。
数组还有一种叫自动计数(automatic counting)的快速初始化方法,就是让编译器按初始化值的个数去决定数组的大小:int c[ ] = { 1, 2, 3, 4 };
现在,如果决定增加另一个元素到这个数组上,只要增加一个初始化值即可,如果以此建立我们的代码,只需在一处作出修改即可。
这样,在修改时出错的机会就减少了。
但怎样确定这个数组的大小呢?用表达式sizeof c / sizeof *c(整个数组的大小除以第一个元素的大小)即可算出,这样,当数组大小改变时它不需要修改。
for ( int i = 0; i < sizeof c /sizeof *c; i++)
c[i]++;
因为结构也是一种集合类型,所以它们也可以用同样的方式初始化。
因为C风格的struct的所有成员都是public型的,所以它们的值可以直接指定。
struct X {
int i;
float f;
char c;
};
X x1 = { 1, 2.2, 'c’ };
如果有一个这种struct的数组,也可以用嵌套的大括号来初始化每一个对象:
X x2[3] = { {1, 1.1, 'a’}, {2, 2.2, 'b’}};
这里,第三个对象被初始化为零。
如果struct中有私有成员(典型的情况就是C++中设计良好的类),或即使所有成员都是公共成员,但有构造函数,情况就不一样了。
在上例中,初始值被直接赋给了集合中的每个元素,但构造函数是通过正式的接口来强制初始化的。
这里,构造函数必须被调用来完成初始化,因此,如果有一个下面的struct类型:
struct Y {
float f;
int i;
Y(int a);
};
必须指示构造函数调用,最好的方法像下面这样:
Y y1[ ] = { Y(1), Y(2), Y(3) };
这样就得到了三个对象和进行了三次构造函数调用。
只要有构造函数,无论是所有成员都是公共的struct还是一个带私有成员的class,所有的初始化工作都必须通过构造函数来完成,即使正在对一个集合初始化。
下面是多构造函数参数的又一个例子:
//: C06:Multiarg.cpp
// From Thinking in C++, 2nd Edition
// Available at
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
// Multiple constructor arguments
// with aggregate initialization
#include <iostream>
using namespace std;
class Z {
int i, j;
public:
Z(int ii, int jj);
void print();
};
Z::Z(int ii, int jj) {
i = ii;
j = jj;
}
void Z::print() {
cout < < "i = " < < i < < ", j = " < < j < < endl;
}
int main() {
Z zz[] = { Z(1,2), Z(3,4), Z(5,6), Z(7,8) };
for(int i = 0; i < sizeof zz / sizeof *zz; i++)
zz[i].print();
} ///:~
注意:这看起来就好象对数组中的每个对象都调用显式的构造函数。
、、、、、、、、、、、、
/////////////////////////////////////////////////////////
该问题涉及到数据类型初始化的问题,现将C语言中数据类型初始化总结如下
简单变量的初始化形式如下:数据类型变量名=初始化值;
例如,定义整型变量a,并给其初始化值10的语句如下
int a=10;
数组的初始化,需要通过一常量数据列表,对其数组元素分别进行初始化,形式如下:
数据类型数组名称〔数组长度〕={初始化值1,初始化值2,…, 初始化值n};
例如,定义长度为5的整型数组,并对其初始化的语句如下:
int A[5]={20,21,0,3,4};
结构体变量的初始化方式与数组类似,分别给结构体的成员变量以初始值,而结构体成员变量的初始化遵循简单变量或数组的初始化方法。
具体的形式如下:
struct 结构体标识符
{
成员变量列表;
…
};
struct结构体标识符变量名={初始化值1,初始化值2,…, 初始化值n };
例如,定义struct Point类型变量,并初始化的语句如下:
struct Point oP1={0.0,0.2,0.3};
struct Point类型变量oP1的三个成员变量的值分别为
oP1.x=0.0,
oP1.y=0.2
oP1.z=0.3
由于定义结构体变量有三种方法,因此初始化结构体变量的方法对应有三种,上面已经介绍了其中的一种形式,其他两种形式如下:struct Point
{
double x;
double y;
double z;
} oP1={0.0,0.2,0.3}; struct
{
double x;
double y;
double z;
} oP1={0.0,0.2,0.3};
在初始化结构体变量时候,既可以初始化其全部成员变量,也可
以仅仅对其中部分的成员变量进行初始化。
例如:
struct Student
{
long id;
char name[20];
char sex;
}a= {0};
其相当于a.id=0;=“”;a.sex='\0x0’。
仅仅对其中部分的成员变量进行初始化,要求初始化的数据至少有一个,其他没有初始化的成员变量由系统完成初始化,为其提供缺省的初始化值。
各种基本数据类型的成员变量初始化缺省值如表9-1所示。
数据类型
缺省初始化值
Int 0
Char '\0x0’
float 0.0
double 0.0
char Array[n] ”
int Array[n] {0,0 0
对于复杂结构体类型变量的初始化,同样遵循上述规律,对结构体成员变量分别赋予初始化值。
例如:
struct Line
{
int id;
struct Point StartPoint;
struct Point EndPoint;
}oLine1={0,
{0,0,0},
{100,0,0}
};
其中常量0用于初始化oLine1的基本类型成员变量id;常量列表{0,0,0}用于初始化oLine1的struct Point类型成员变量StartPoint;常量列表{100,0,0}用于初始化oLine1的struct Point类型成员变量EndPoint。
当结构体中有字符串Array时原则上用组合{{0}}来初始化,当用这个结构体定义一个array时更需要三个嵌套的{{{0}}} 不奇怪了。
How to initialise structures to all-elements-zero-or-null
I understand that in the United States, the word `initialise' is spelled with a z. So for the benefit of Google users,
How to initialize structures to all-elements-zero-or-null [ Home page | Random stuff ]
(This page is here because this is a question which seems to come up reasonably frequently, and it's useful to have the answer all written down in one place to refer to.)
When you declare a structure in `static storage' (meaning with the keyword static or at file scope), it is initialised with all numeric members zero and all pointers null. How should one achieve the same thing when initialising a structure in automatic or dynamic storage? Let's assume that this structure is defined by somebody else (say, POSIX), and in the normal fashion of such standards, all you know about the structure is that it contains at a minimum a certain set of elements; you do not know its exact
contents.
Commmon answers look something like this:
int foo(void) {
struct bar baz;
memset(&baz, 0, sizeof baz);
}
int quux(void) {
struct bar *fish;
fish = calloc(sizeof *fish, 0);
}
Unfortunately, neither achieves the intended effect. There is no guarantee that the machine representation of zero is all-bits-zero, nor that the representation of a null pointer is all-bits-zero. (Note that the fact that you can initialise a null pointer by setting it to `0' doesn't signify here: the standard defines a `null pointer constant' as 0 or (void*)0, but makes no statement about its in-memory representation. It is not even guaranteed that different types of pointer have the same representation.)
The correct answer is to say
struct bar baz = {0};
or, for dynamic storage, something like
struct bar *baz, zz = {0};
baz = malloc(sizeof *baz);
*baz = zz;
-- note the ugly declaration of zz. You can do slightly better with a macro such as
/* alloc_struct TAG P
* Enough memory to hold a struct TAG is allocated and assigned to P, and the
* memory is initialised so that all numeric elements of *P are
zero and all
* pointer elements null. */
#define alloc_struct(tag, p) do
{ struct tag aszero ## tag = {0}; p = malloc(sizeof *p); *p = aszero ## tag; }
while (0)
Not very nice. If you're using GCC or another compiler which supports typeof, you can do
#define alloc_struct(p) do
{ typeof(*p) aszero_ ## p = {0}; p = malloc(sizeof *p); *p = aszero_ ## p; }
while (0)
-- but since the whole point of this exercise is to make the
code portable, that's kind of pointless. As an alternative, you
could declare a static `zeroed' instance of struct foo in the same
header as the structure is defined, and then assign that to things
later. None of these has the virtue of being elegant or pretty.
(It's also worth noting that if you use = {0} to initialise a structure which contains other aggregate types, current versions
of GCC will issue a warning such as,
file.c: In function `func':
file.c:42: warning: missing braces around initializer
file.c:42: warning: (near initialization for `s.aggregate')
-- this is irritating, but there's not much that can be done
about it.)
Justification
The typical objections to this approach are `You don't know
what's in the structure, so you don't know whether the first element can be initialised to 0'; or, `What happens to the
elements of the structure after the first?' Both are wrong. The basic game here is that:
1.You don't have to initialise every element of a structure, but can initialise only the first one; you don't need nested {} even to initialise aggregate members of a structure.
2.Anything in C can be initialised with = 0; this initialises numeric elements to zero and pointers null.
From the Standard (actually from the final draft, but I don't think these have changed since then),
[6.7.8.20] If the aggregate contains
elements or members that are aggregates
or unions, or if the first member of a union
is an aggregate or union, these rules apply
recursively to the subaggregates or
contained unions. If the initializer of a
subaggregate or contained union begins
with a left brace, the initializers enclosed
by that brace and its matching right brace
initialize the elements or members of the
subaggregate or the first member of the
contained union. Otherwise, only enough
initializers from the list are taken to
account for the elements or members of
the subaggregate or the first member of
the contained union; any remaining
initializers are left to initialize the next
element or member of the aggregate of
which the current subaggregate or
contained union is a part.
[6.7.8.21] If there are fewer initializers
in a brace-enclosed list than there are
elements or members of an aggregate, or
fewer characters in a string literal used to
initialize an array of known size than there
are elements in the array, the remainder of
the aggregate shall be initialized implicitly
the same as objects that have static
storage duration.
so struct foo bar = {0} always initialises the first element of the first subelement of bar as if it had been initialised with = 0 and initialises the rest `[in] the same [way] as objects that have static storage duration'.
It would be neater to be able to say struct foo bar = {}, and some compilers (e.g. GCC) permit this, but the ANSI grammar requires an initialiser list to be non-empty.
If you don't believe me, see, e.g., this article on ng.c. Who cares?
Arguably, only pedants like me. The portability argument is on the face of it quite a strong one, but actually I think it's a bit of a sham. After all, there's so much bad C code out there which just callsmemset that you'd be mad to build a new processor or MMU which didn't use all-bits-zero as the representation of a zero numeric value or as an invalid pointer which can be used as a null pointer.
Copyright (c) 2002 Chris Lightfoot. All rights reserved.。