Chapter 6 - Structures(二)

6.2 Structures and Functions

The only legal operations on a structure are copying it or assigning to it as a unit, taking its address with &, and accessing its members. Copy and assignment include passing arguments to functions and returning values from functions as well. Structures may not be compared. A structure may be initialized by a list of constant member values; an automatic structure may also be initialized by an assignment.

结构的合法操作只有几种:作为一个整体复制和赋值,通过&运算符取地址,访问其成员。其中,复制和赋值包括向函数传递参数以及从函数返回值。结构之间不可以进行比较。可以用一个常量成员值列表初始化结构,自动结构也可以通过赋值进行初始化。

Let us investigate structures by writing some functions to manipulate points and rectangles. There are at least three possible approaches: pass components separately, pass an entire structure, or pass a pointer to it. Each has its good points and bad points.

为了更进一步地理解结构,我们编写几个对点和矩形进行操作的函数。至少可以通过3种可能的方法传递结构:一是分别传递各个结构成员,二是传递整个结构,三是传递指向结构的指针。这3 种方法各有利弊。

The first function, makepoint, will take two integers and return a point structure:

/* makepoint: make a point from x and y components */

struct point makepoint(int x, int y)

{

struct point temp;

temp.x = x;

temp.y = y;

return temp;

}

Notice that there is no conflict between the argument name and the member with the same name; indeed the re-use of the names stresses the relationship.

注意,参数名和结构成员同名不会引起冲突。事实上,使用重名可以强调两者之间的关系。

makepoint can now be used to initialize any structure dynamically, or to provide structure arguments to a function:

现在可以使用makepoint函数动态地初始化任意结构,也可以向函数提供结构类型的参数。例如:

struct rect screen;

struct point middle;

struct point makepoint(int, int);

screen.pt1 = makepoint(0,0);

screen.pt2 = makepoint(XMAX, YMAX);

middle = makepoint((screen.pt1.x + screen.pt2.x)/2,(screen.pt1.y + screen.pt2.y)/2);

The next step is a set of functions to do arithmetic on points. For instance,

/* addpoints: add two points */

struct addpoint(struct point p1, struct point p2)

{

p1.x += p2.x;

p1.y += p2.y;

return p1;

}

Here both the arguments and the return value are structures. We incremented the components in p1 rather than using an explicit temporary variable to emphasize that structure parameters are passed by value like any others.

其中,函数的参数和返回值都是结构类型。之所以直接将相加所得的结果赋值给p1,而没有使用显式的临时变量存储,是为了强调结构类型的参数和其它类型的参数一样,都是通过值传递的。

As another example, the function ptinrect tests whether a point is inside a rectangle, where we have adopted the convention that a rectangle includes its left and bottom sides but not its top and right sides:

下面来看另外一个例子。函数prinrect 判断一个点是否在给定的矩形内部。我们采用这样一个约定:矩形包括其左侧边和底边,但不包括顶边和右侧边。

/* 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;

}

This assumes that the rectangle is presented in a standard form where the pt1 coordinates are less than the pt2 coordinates. The following function returns a rectangle guaranteed to be in canonical form:

这里假设矩形是用标准形式表示的,其中pt1的坐标小于pt2的坐标。下列函数将返回一个规范形式的矩形:

#define min(a, b) ((a) < (b) ? (a) : (b))

#define max(a, b) ((a) > (b) ? (a) : (b))

/* canonrect: canonicalize coordinates of rectangle */

struct rect canonrect(struct rect r)

{

struct rect temp;

temp.pt1.x = min(r.pt1.x, r.pt2.x);

temp.pt1.y = min(r.pt1.y, r.pt2.y);

temp.pt2.x = max(r.pt1.x, r.pt2.x);

temp.pt2.y = max(r.pt1.y, r.pt2.y);

return temp;

}

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. Structure pointers are just like pointers to ordinary variables. The declaration

如果传递给函数的结构很大,使用指针方式的效率通常比复制整个结构的效率要高。结构指针类似于普通变量指针。声明

struct point *pp;

says that pp is a pointer to a structure of type struct point. If pp points to a point structure, *pp is the structure, and (*pp).x and (*pp).y are the members. To use pp, we might write, for example,

pp定义为一个指向struct point类型对象的指针。如果pp指向一个point结构,那么*pp即为该结构,而(*pp).x(*pp).y则是结构成员。可以按照下例中的方式使用pp

struct point origin, *pp;

pp = &origin;

printf("origin is (%d,%d)\n", (*pp).x, (*pp).y);

The parentheses are necessary in (*pp).x because the precedence of the structure member operator . is higher then *. The expression *pp.x means *(pp.x), which is illegal here because x is not a pointer.

其中,(*pp).x中的圆括号是必需的,因为结构成员运算符“.”的优先级比“*”的优先级高。表达式*pp.x的含义等价于*(pp.x),因为x不是指针,所以该表达式是非法的。

Pointers to structures are so frequently used that an alternative notation is provided as a shorthand. If p is a pointer to a structure, then

结构指针的使用频度非常高,为了使用方便,C 语言提供了另一种简写方式。假定p 是一个指向结构的指针,可以用

p->member-of-structure

refers to the particular member. So we could write instead

printf("origin is (%d,%d)\n", pp->x, pp->y);

Both . and -> associate from left to right, so if we have

struct rect r, *rp = &r;

then these four expressions are equivalent:

r.pt1.x

rp->pt1.x

(r.pt1).x

(rp->pt1).x

The structure operators . and ->, together with () for function calls and [] for subscripts, are at the top of the precedence hierarchy and thus bind very tightly. For example, given the declaration

在所有运算符中,下面4 个运算符的优先级最高:结构运算符“.”和“->”、用于函数调用的“()”以及用于下标的“[]”,因此,它们同操作数之间的结合也最紧密。例如,对于结构声明

struct {

int len;

char *str;

} *p;

then

++p->len

increments len, not p, because the implied parenthesization is ++(p->len). Parentheses can be used to alter binding: (++p)->len increments p before accessing len, and (p++)->len increments p afterward. (This last set of parentheses is unnecessary.)

将增加len 的值,而不是增加p 的值,这是田为,其中的隐含括号关系是++(p->len)。可以使用括号改变结合次序。例如:(++p)->len将先执行p的加1 操作,再对len执行操作;而(p++)->len则先对len执行操作,然后再将p1(该表达式中的括号可以省略)。

In the same way, *p->str fetches whatever str points to; *p->str++ increments str after accessing whatever it points to (just like *s++); (*p->str)++ increments whatever str points to; and *p++->str increments p after accessing whatever str points to.

同样的道理,*p->str 读取的是指针str 所指向的对象的值;*p->str++先读取指针str 指向的对象的值,然后再将str 1(与*s++相同);(*p->str++将指针str 指向的对象的值加1*p++->str先读取指针str指向的对象的值,然后再将p1


canonicalize 规范化

precedence  n. 优先;居先

hierarchy  n. 层级;等级制度

上一章Chapter 6 - Structures(一)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值