主题:[原创]重新认识struct
建议结合使用《the c programming language》来阅读本文,相关书籍在网上均有电子版.
在描述struct前,我们先来了解一下what is a type?
A type is a concrete representation of a concept.
For example,the c++ built-in type float with its operations +,-,*,etc.,provides a concrete approximation of the mathematical concept of a real number. (摘于《the c++ programming language》chapter 10)
由此,我们可以明确的知道,a type is a concept.这个type包含的不仅仅是一个像int,double这样的一个符号,更多的是在表示一种concept。一个类型的内涵,还包括其运算方式,其使用范围,其用法等等一系列的问题。
现在进行分析,struct是什么:
A structure is a collection of one or more variables, possibly of different types.(K&R 《the c programming language》)
由此可以明确的是,struct组合的是一组concept并把它表示为一个concept.由于这种组合的特殊性,虽然方便但在作为一个整体使用,必然要在一定程度上限定其应用.所以有下:
structures may be copied and assigned to, passed to functions,and returned by functions.(K&R 《the c programming language》)
描述struct的使用方式。
以上具体的描述了struct,为之后理解struct有很重要的意义。
struct实际应用的意义:
通常情况下,我们会用一个struct来定义一个树,定义一个线形表,而不会使用一个类来表示,因为,类是具体对象的抽象,也就是说,我们描述的树和线形表还不够具体到需要用类来描述,其不具体到不需要描述其行为(成员函数)的程度,因此,struct为我们提供了一个很好的描述机制,它组合了一组数据,而又不需要来描述足够具体了实体。
struct基础说明:
1.The keyword struct introduces a structure declaration, which is a list of declarations enclosed in braces. An optional name called a structure tag may follow the word struct.The variables named in a structure are called members.(K&R 《the c programming language》)
例如:
struct point{
int x;
int y;
};
这里point就是structure tag.x,y 就是member.
熟悉各个概念是为了更好的继续阅读以后的文章.
这里还可以谈及一个有关命名的问题,member的名称可以于外部变量相同,因为我们总是可以通过上下文进行区分(they can always be distinguished by context.)更明确的说法是,我们都可以通过变量来区别他们应用的成员.其实,这里设计到的是一个有关块结构的问题,有关块结构的作用域的问题可以参考<<C++ how to program>>chapter 3(H.M.Deitel,P.J.Deitel著)
附加语法知识:在定义任何自定义类型及其初始化时后面都要在大括号后面加一个";"表示结束.其他情况的大括号后面均无需加";".关于内部类型和自定义类型的概念参见<<the c++ programming language>>.
2.A structure declaration that is not followed by a list of variables reserves no storage; it merely describes a template or shape of a structure.(K&R 《the c programming language》)
也就是说,结构的申明只是在描述一种模板,而不占据空间.
3.初始化问题:
A structure can be initialized by following its definition with a list of initializers, each a constant expression, for the
members:
struct point maxpt = { 320, 200 }; //注意只有在定义的同时可以使用这样的赋值形式.
任何类型都可以在定义的时候初始化,并且都是用赋值符号来实现.
假如没有在定义时候初始化,就需要用 varialbe.member(书中是structure-name.member,笔者觉得用variable描述更加妥当)
4.Structures can be nested.
支持嵌套.
eg.:
struct point{
int x;
int y;
};
struct rect{
struct point p1;
struct point p2;
};
5.函数对结构的使用
eg.:
/* ptinrect: return 1 if p in r, 0 if not */
int ptinrect(struct point p, struct rect r)
{
return p.x >= r.pt1.x && p.x < r.pt2.x && p.y >= r.pt1.y && p.y < r.pt2.y;
}
以上种种显示,结构体和一般的变量没有本质的区别,其不同仅仅是在定义上.
由5中函数对rectangle的判断,可以分析出在处理长方形问题上的方法,一个长方形可以用其对角的两个点表示,并且可由这两个点解决很多实际的问题,比如上面的判断一个点是否在长方形内部.
在这里我对几个概念做一下总结性描述:
structure:结构体,通常一个结构体通过一个结构体标记表示(structure tag)
structure varialbe:结构体变量.像一般变量一样,不同的是其是由结构体定义(申明).
虽然结构体和类在c++中没有本质的区别,但是我们依然不混用他们,其原因就是他们内在含义的不同,而这几个概念就是他们含义的一种体现.
6.结构体使用技巧,传递指针而非结构体变量本身.
If a large structure is to be passed to a function, it is generally more efficient to pass a pointer than to copy the whole structure.(K&R 《the c programming language》)
这里的高效,体现在传递指针不需要为变元的副本拷贝提供过大的开销,这样的问题特别出现在巨大的结构体和类上面,对于一个小的结构,虽然从本质上来说使用指针来提高效率作用颇小,但是却因为一些微妙的原因值得我们去做.关于函数参数的传递问题,在函数参数的按引用传递和按值传递上表现的很明显,相关内容建议参考<<c++ how to program>>.
前面说过,结构体和一般的变量没有本质的区别,其不同仅仅是在定义上.所以说,在对于指针的使用方面,结构体造常规使用.唯一特殊的是,为了方便的使用指针,出现了"->"运算符号.使用方法是:指针->成员.
注意:(*pp).x 括号是必须的,因为.的优先级高于*.优先级参见<<the c programming language>>Page:50.
实例: *p->str++ 表示的就是 结构 p 指针中的 str 加1 在指向地址对应的值.注意:*,++是从右到左的.
结构体实例:
选自<<the c programming language>>
问题:Consider writing a program to count the occurrences of each C keyword.(写一个程序计算c中的关键字)
分析:对于问题,我们必须要分析的目标是:keyword和keyword的个数,更显然的问题是,一个keyword一定需要一个keyword数量于之对应.显然,一组数据的依赖关系产生了,结构体就是用于来处理相关数据的.由此,没有理由不使用structure.
小结:何时使用结构体?当我们遇见一组相关数据的时候,使用结构体,相关数据的一种情况就是,一个数据伴随另外一个数据产生.
求解:
建立结构体:
struct key{
char *word;
int count;
}keytab[]={
"auto", 0,
"break", 0,
"case", 0,
"char", 0,
"const", 0,
"continue", 0,
"default", 0,
/* ... */
"unsigned", 0,
"void", 0,
"volatile", 0,
"while", 0
}; //涉及知识,结构体定义,结构体初始化(定义同时初始化).
这里为了大家对初始化更加清晰的了解,做一下解释:
对于上面的结构体,我们还可以这样描述:
struct key{
char *word;
int count;
}keytab[]={
{"auto", 0},
{"break", 0},
{"case", 0},
{"char", 0},
{"const", 0},
{"continue", 0},
{"default", 0},
/* ... */
{"unsigned", 0},
{"void", 0},
{"volatile", 0},
{"while", 0}
}; //这里加上大括号,表示是一组数据,也就是结构体变量的一个数据,那么这样的表示马上使结构体和一般的变量统一起来了,有所区别的仅仅是每组数据不是单个数据而已.
具体程序请参考原书,因为具体程序在本文中的意义并不大,不做详细描述.
完.
最近更新日期:05-08-10