回 帖 发 新 帖 刷新版面

主题:[原创]重新认识struct

重新认识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

回复列表 (共11个回复)

沙发

支持!

板凳

好!赶紧出续。

3 楼

..........顶

4 楼

就这么多了。。。。。。

5 楼

贴到个人blog里!

6 楼

BLOG很方便。
主页也不错,就是比较难维护,不过可以放一些东西给人下载。
我的主页上有写文章和书下载。
暂时放这里:
http://killercat.goofar.com

7 楼

好文章

8 楼

请问楼主"《the c programming language》来阅读本文,相关书籍在网上均有电子版"
在哪可以找到?非常感谢!!!

9 楼

E-mail:jackywang1000@yahoo.com.cn

10 楼

//Visual C++6.0, 好帖子,顶!!!

#include <iostream>
using namespace std;

typedef enum {A,B,C,D,E} SchoolName;
typedef enum {FEMALE,MALE} SexType;

struct Component
{
    Component(char *s, SexType sx, SchoolName sName, int scor)
    {
        strcpy(event, s);
        sex = sx;
        school = sName;
        score = scor;
    }
    char        event[5];
    SexType    sex;
    SchoolName school;
    int        score;
};

ostream & operator << (ostream &os, Component &obj)
{
    os  << obj.event << endl
        << obj.sex << endl
        << obj.school << endl
        << obj.score << endl;
    return os;
}

void main()
{
    Component a("He", MALE, A, 99);
    cout << a;
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册