⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter6.html

📁 Kernighan and Ritchie - The C Programming Language c程序设计语言(第二版)称作是C语言学习的圣经
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<html><head><title>Chapter 6 - Structures</title></head><body><hr><p align="center"><a href="chapter5.html">Back to Chapter 5</a>&nbsp;--&nbsp;<a href="kandr.html">Index</a>&nbsp;--&nbsp;<a href="chapter7.html">Chapter 7</a><p><hr><h1>Chapter 6 - Structures</h1>A structure is a collection of one or more variables, possibly of differenttypes, grouped together under a single name for convenient handling.(Structures are called ``records'' in some languages, notably Pascal.)Structures help to organize complicated data, particularly in large programs,because they permit a group of related variables to be treated as a unitinstead of as separate entities.<p>One traditional example of a structure is the payroll record: an employee isdescribed by a set of attributes such as name, address, social securitynumber, salary, etc. Some of these in turn could be structures: a name hasseveral components, as does an address and even a salary. Another example,more typical for C, comes from graphics: a point is a pair of coordinate, arectangle is a pair of points, and so on.<p>The main change made by the ANSI standard is to define structure assignment- structures may be copied and assigned to, passed to functions, andreturned by functions. This has been supported by most compilers for manyyears, but the properties are now precisely defined. Automatic structures andarrays may now also be initialized.<h2><a name="s6.1">6.1 Basics of Structures</a></h2>Let us create a few structures suitable for graphics. The basic object is apoint, which we will assume has an <em>x</em> coordinate and a <em>y</em>coordinate, both integers.<p align="center"><img src="pic61.gif"><p>The two components can be placed in a structure declared like this:<pre>   struct point {       int x;       int y;   };</pre>The keyword <tt>struct</tt> introduces a structure declaration, which is a listof declarations enclosed in braces. An optional name called a <em>structuretag</em> may follow the word <tt>struct</tt> (as with <tt>point</tt> here). The tagnames this kind of structure, and can be used subsequently as a shorthand forthe part of the declaration in braces.<p>The variables named in a structure are called <em>members</em>. A structuremember or tag and an ordinary (i.e., non-member) variable can have the samename without conflict, since they can always be distinguished by context.Furthermore, the same member names may occur in different structures,although as a matter of style one would normally use the same names only forclosely related objects.<p>A <tt>struct</tt> declaration defines a type. The right brace that terminatesthe list of members may be followed by a list of variables, just as for anybasic type. That is,<pre>   struct { ... } x, y, z;</pre>is syntactically analogous to<pre>   int x, y, z;</pre>in the sense that each statement declares <tt>x</tt>, <tt>y</tt> and <tt>z</tt> to bevariables of the named type and causes space to be set aside for them.<p>A structure declaration that is not followed by a list of variables reservesno storage; it merely describes a template or shape of a structure. If thedeclaration is tagged, however, the tag can be used later in definitions ofinstances of the structure. For example, given the declaration of <tt>point</tt>above,<pre>   struct point pt;</pre>defines a variable <tt>pt</tt> which is a structure of type <tt>struct point</tt>.A structure can be initialized by following its definition with a list ofinitializers, each a constant expression, for the members:<pre>   struct maxpt = { 320, 200 };</pre>An automatic structure may also be initialized by assignment or by calling afunction that returns a structure of the right type.<p>A member of a particular structure is referred to in an expression by aconstruction of the form<p>&nbsp;&nbsp;<em>structure-name.member</em><p>The structure member operator ``.'' connects the structure name and themember name. To print the coordinates of the point <tt>pt</tt>, for instance,<pre>   printf("%d,%d", pt.x, pt.y);</pre>or to compute the distance from the origin (0,0) to <tt>pt</tt>,<pre>   double dist, sqrt(double);   dist = sqrt((double)pt.x * pt.x + (double)pt.y * pt.y);</pre>Structures can be nested. One representation of a rectangle is a pair ofpoints that denote the diagonally opposite corners:<p align="center"><img src="pic62.gif"><p><pre>   struct rect {       struct point pt1;       struct point pt2;   };</pre>The <tt>rect</tt> structure contains two <tt>point</tt> structures. If we declare<tt>screen</tt> as<pre>   struct rect screen;</pre>then<pre>   screen.pt1.x</pre>refers to the <em>x</em> coordinate of the <tt>pt1</tt> member of <tt>screen</tt>.<h2><a name="s6.2">6.2 Structures and Functions</a></h2>The only legal operations on a structure are copying it or assigning to it asa unit, taking its address with <tt>&amp;</tt>, and accessing its members. Copyand assignment include passing arguments to functions and returning valuesfrom functions as well. Structures may not be compared. A structure may beinitialized by a list of constant member values; an automatic structure mayalso be initialized by an assignment.<p>Let us investigate structures by writing some functions to manipulate pointsand rectangles. There are at least three possible approaches: pass componentsseparately, pass an entire structure, or pass a pointer to it. Each has itsgood points and bad points.<p>The first function, <tt>makepoint</tt>, will take two integers and return a<tt>point</tt> structure:<pre>   /* 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;   }</pre>Notice that there is no conflict between the argument name and the memberwith the same name; indeed the re-use of the names stresses the relationship.<p><tt>makepoint</tt> can now be used to initialize any structure dynamically,or to provide structure arguments to a function:<pre>   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);</pre>The next step is a set of functions to do arithmetic on points. For instance,<pre>   /* addpoints:  add two points */   struct addpoint(struct point p1, struct point p2)   {       p1.x += p2.x;       p1.y += p2.y;       return p1;   }</pre>Here both the arguments and the return value are structures. We incrementedthe components in <tt>p1</tt> rather than using an explicit temporary variableto emphasize that structure parameters are passed by value like any others.<p>As another example, the function <tt>ptinrect</tt> tests whether a point isinside a rectangle, where we have adopted the convention that a rectangleincludes its left and bottom sides but not its top and right sides:<pre>   /* ptinrect:  return 1 if p in r, 0 if not */   int ptinrect(struct point p, struct rect r)   {       return p.x &gt;= r.pt1.x && p.x &lt; r.pt2.x           && p.y &gt;= r.pt1.y && p.y &lt; r.pt2.y;   }</pre>This assumes that the rectangle is presented in a standard form where the<tt>pt1</tt> coordinates are less than the <tt>pt2</tt> coordinates. The followingfunction returns a rectangle guaranteed to be in canonical form:<pre>   #define min(a, b) ((a) &lt; (b) ? (a) : (b))   #define max(a, b) ((a) &gt; (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;   }</pre>If a large structure is to be passed to a function, it is generally moreefficient to pass a pointer than to copy the whole structure. Structurepointers are just like pointers to ordinary variables. The declaration<pre>   struct point *pp;</pre>says that <tt>pp</tt> is a pointer to a structure of type <tt>struct point</tt>. If<tt>pp</tt> points to a <tt>point</tt> structure, <tt>*pp</tt> is the structure, and<tt>(*pp).x</tt> and <tt>(*pp).y</tt> are the members. To use <tt>pp</tt>, we mightwrite, for example,<pre>   struct point origin, *pp;   pp = &origin;   printf("origin is (%d,%d)\n", (*pp).x, (*pp).y);</pre>The parentheses are necessary in <tt>(*pp).x</tt> because the precedence ofthe structure member operator <tt>.</tt> is higher then <tt>*</tt>. Theexpression <tt>*pp.x</tt> means <tt>*(pp.x)</tt>, which is illegal herebecause <tt>x</tt> is not a pointer.<p>Pointers to structures are so frequently used that an alternative notation isprovided as a shorthand. If <tt>p</tt> is a pointer to a structure, then<pre>   p-&gt;<em>member-of-structure</em></pre>refers to the particular member. So we could write instead<pre>   printf("origin is (%d,%d)\n", pp-&gt;x, pp-&gt;y);</pre>Both <tt>.</tt> and <tt>-&gt;</tt> associate from left to right, so if wehave <pre>   struct rect r, *rp = &r;</pre>then these four expressions are equivalent:<pre>   r.pt1.x   rp-&gt;pt1.x   (r.pt1).x   (rp-&gt;pt1).x</pre>The structure operators <tt>.</tt> and <tt>-&gt;</tt>, together with<tt>()</tt> for function calls and <tt>[]</tt> for subscripts, are at the topof the precedence hierarchy and thus bind very tightly. For example, giventhe declaration<pre>   struct {       int len;       char *str;   } *p;</pre>then<pre>   ++p-&gt;len</pre>increments <tt>len</tt>, not <tt>p</tt>, because the implied parenthesizationis <tt>++(p-&gt;len)</tt>. Parentheses can be used to alter binding:<tt>(++p)-&gt;len</tt> increments <tt>p</tt> before accessing <tt>len</tt>,and <tt>(p++)-&gt;len</tt> increments <tt>p</tt> afterward. (This last set ofparentheses is unnecessary.)<p>In the same way, <tt>*p-&gt;str</tt> fetches whatever <tt>str</tt> points to;<tt>*p-&gt;str++</tt> increments <tt>str</tt> after accessing whatever itpoints to (just like <tt>*s++</tt>); <tt>(*p-&gt;str)++</tt> incrementswhatever <tt>str</tt> points to; and <tt>*p++-&gt;str</tt> increments<tt>p</tt> after accessing whatever <tt>str</tt> points to.<h2><a name="s6.3">6.3 Arrays of Structures</a></h2>Consider writing a program to count the occurrences of each C keyword.We need an array of character strings to hold the names, and an array ofintegers for the counts. One possibility is to use two parallel arrays,<tt>keyword</tt> and <tt>keycount</tt>, as in<pre>   char *keyword[NKEYS];   int keycount[NKEYS];</pre>But the very fact that the arrays are parallel suggests a differentorganization, an array of structures. Each keyword is a pair:<pre>   char *word;   int cout;</pre>and there is an array of pairs. The structure declaration<pre>   struct key {       char *word;       int count;   } keytab[NKEYS];</pre>declares a structure type <tt>key</tt>, defines an array <tt>keytab</tt> ofstructures of this type, and sets aside storage for them. Each element of thearray is a structure. This could also be written<pre>   struct key {       char *word;       int count;   };

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -