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

📄 faqcat6b6b.html

📁 this is a mirrored site c-faq. thought might need offline
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN"><!-- This collection of hypertext pages is Copyright 1995-2005 by Steve Summit. --><!-- Content from the book "C Programming FAQs: Frequently Asked Questions" --><!-- (Addison-Wesley, 1995, ISBN 0-201-84519-9) is made available here by --><!-- permission of the author and the publisher as a service to the community. --><!-- It is intended to complement the use of the published text --><!-- and is protected by international copyright laws. --><!-- The on-line content may be accessed freely for personal use --><!-- but may not be published or retransmitted without explicit permission. --><!-- --><!-- this page built Sat Dec 24 21:47:45 2005 by faqproc version 2.7 --><!-- from source file struct.sgml dated Wed Dec 21 16:15:32 2005 --><!-- corresponding to FAQ list version 4.0 --><html><!-- Mirrored from c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=struct by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:57:33 GMT --><head><base ><meta name=GENERATOR content="faqproc"><title>Structures, Unions, and Enumerations</title></head><body bgcolor="#ffffff"><H1>2. Structures, Unions, and Enumerations</H1><a name="typedef"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/typedef.html"><!-- qtag -->Question 2.1</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's the difference betweenthese two declarations?<pre>	struct x1 { ... };	typedef struct { ... } x2;</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The first form declares a <a href="../../sx1/index.html#structure tag"><dfn>structure tag</dfn></a>;the second declares a <a href="../../sx1/index.html#typedef"><dfn>typedef</dfn></a>.Themaindifference isthatthe second declaration is of a slightly more abstracttype--itsusers don't necessarily know that it is a structure,andthe keyword <TT>struct</TT> is not used when declaring instances ofit:<pre>	x2 b;</pre></p><p>Structures declared withtags,on the other hand,must be defined with the<pre>	struct x1 a;</pre>form.<a href="../../struct/cplpl.html" rel=subdocument>[footnote]</a></p><p>(It'salso possible to play it both ways:<pre>	typedef struct x3 { ... } x3;</pre>It's legal,if potentially obscure,to use the same name for both the tag and the typedef,since they live in separate namespaces.See question <a href="faqcatd3c2.html?sec=decl#namespace">1.29</a>.)<hr><hr><hr><a name="impltypedef"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/impltypedef.html"><!-- qtag -->Question 2.2</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why doesn't<pre>struct x { ... };x thestruct;</pre>work?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>C is not C++.Typedefnames are not automatically generated for structure tags.Either declare structure instances using the <TT>struct</TT> keyword:<pre>	struct x thestruct;</pre>or declare a typedef when you declare a structure:<pre>	typedef struct { ... } x;	x thestruct;</pre>See also questions<a href="faqcatd3c2.html?sec=decl#selfrefstruct">1.14</a>and<a href="faqcat6b6b.html?sec=struct#typedef">2.1</a>.<hr><hr><hr><a name="selfref"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/selfref.html"><!-- qtag -->Question 2.3</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Can a structure contain a pointerto itself?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Most certainly.A problem can arise if you try to use typedefs;seequestions <a href="faqcatd3c2.html?sec=decl#selfrefstruct">1.14</a> and <a href="faqcatd3c2.html?sec=decl#mutrefstructs">1.15</a>.<hr><hr><hr><a name="opaquetypes"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/opaquetypes.html"><!-- qtag -->Question 2.4</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I implementopaque (abstract) data types in C?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>One good way isfor clientsto use structure pointers(perhaps additionally hidden behind typedefs)which point to structure types which are not publicly defined.In other words,a client uses structure pointers(and calls functions accepting and returning structure pointers)without knowinganything aboutwhat the fields of the structure are.(As long asthe details of the structure aren'tneeded--e.g. aslong asthe<TT>-&gt;</TT>and<TT>sizeof</TT>operators are not used--Cis perfectly happyto handle pointers to structures ofincomplete type.<a href="../../struct/jst3.html" rel=subdocument>[footnote]</a>)Only within the source filesimplementing the abstract data typearecomplete declarations for the structures actually in scope.</p><p>See also question <a href="faqcat7d4b.html?sec=ansi#structinproto">11.5</a>.</p><p>Additional links:<br><br><a href="../../struct/opaque.examp.html">example</a><br><br><a href="../../struct/sd1.html" rel=subdocument>slightly shorter, slightly goofier example</a><hr><hr><hr><a name="oop"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/oop.html"><!-- qtag -->Question 2.4b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Is there a good way of simulating OOP-style inheritance,or other OOP features,in C?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It's straightforward to implement simple ``methods''by placing function pointers in structures.You can make various clumsy, brute-force attempts at inheritanceusing the preprocessoror by having structures contain ``base types''as initial subsets,but it won't be perfect.There's obviously no operator overloading,and overriding(i.e. of ``methods'' in ``derived classes'')would have to be done by hand.</p><p>Obviously, if you need ``real'' OOP,you'll want to use a language that supports it,such as C++.</p><p>Additional links:An<a href="../../struct/oop.jxh.html">article by James Hu</a>exploring some possibilities in more detail.<hr><hr><hr><a name="fcnproto"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/fcnproto.html"><!-- qtag -->Question 2.5</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why does the declaration<pre>extern int f(struct x *p);</pre>give mean obscurewarning messageabout``struct x declared inside parameter list''?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcat7d4b.html?sec=ansi#structinproto">11.5</a>.<hr><hr><hr><a name="structhack"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/structhack.html"><!-- qtag -->Question 2.6</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I came across some code that declared a structurelike this:<pre>struct name {	int namelen;	char namestr[1];};</pre>and then did some tricky allocation to makethe<TT>namestr</TT>array act like ithad several elements,with the numberrecorded by <TT>namelen</TT>.How does this work?Isitlegal or portable?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It's not clear if it's legal or portable,but it is rather popular.An implementation of the techniquemight looksomething like this:<pre>#include &lt;stdlib.h&gt;#include &lt;string.h&gt;struct name *makename(char *newname){	struct name *ret =		malloc(sizeof(struct name)-1 + strlen(newname)+1);				/* -1 for initial [1]; +1 for \0 */	if(ret != NULL) {		ret-&gt;namelen = strlen(newname);		strcpy(ret-&gt;namestr, newname);	}	return ret;}</pre>This function allocatesan instance of the <TT>name</TT> structurewith the size adjustedso that the <TT>namestr</TT> field can hold the requested name(not just one character,as the structure declaration would suggest).</p><p>Despite its popularity,the technique is also somewhat notorious:Dennis Ritchie has called it``unwarranted chumminess with theC implementation,''and anofficial interpretationhas deemed that itis notstrictly conformingwith the C Standard,althoughit does seem to work underall known implementations.(Compilers which check array bounds carefullymight issue warnings.)</p><p>Another possibility isto declare the variable-size element verylarge, rather than very small.Theabove examplecould be rewritten like this:<pre>#include &lt;stdlib.h&gt;#include &lt;string.h&gt;#define MAXSIZE 100struct name {	int namelen;	char namestr[MAXSIZE];};struct name *makename(char *newname){	struct name *ret =		malloc(sizeof(struct name)-MAXSIZE+strlen(newname)+1);								/* +1 for \0 */	if(ret != NULL) {		ret-&gt;namelen = strlen(newname);		strcpy(ret-&gt;namestr, newname);	}	return ret;}</pre>where <TT>MAXSIZE</TT> is larger than any name which will be stored.However,it looks like this technique is disallowed bya strict interpretation of the Standardas well.Furthermore,either of these ``chummy'' structures must be used with care,since the programmer knows more about their size than the compiler does.</p><p>Of course, to be truly safe,the right thing to do is use a character pointer instead of an array:<pre>#include &lt;stdlib.h&gt;#include &lt;string.h&gt;struct name {	int namelen;	char *namep;};struct name *makename(char *newname){	struct name *ret = malloc(sizeof(struct name));	if(ret != NULL) {		ret-&gt;namelen = strlen(newname);		ret-&gt;namep = malloc(ret-&gt;namelen + 1);		if(ret-&gt;namep == NULL) {			free(ret);			return NULL;		}		strcpy(ret-&gt;namep, newname);	}	return ret;}</pre>(Obviously, the ``convenience'' of havingthe length and the string stored in the same block of memoryhas now been lost,and freeing instances of this structure will require two calls to <TT>free</TT>;see question <a href="faqcatbafd.html?sec=malloc#freeforall">7.23</a>.)</p><p>When the data type being stored is characters,as in the above examples,it is straightforward to coalesce the two calls to <TT>malloc</TT> into one,to preserve contiguity(and therefore rescue the ability to use a single call to <TT>free</TT>):<pre>struct name *makename(char *newname){	char *buf = malloc(sizeof(struct name) +				strlen(newname) + 1);	struct name *ret = (struct name *)buf;	ret-&gt;namelen = strlen(newname);	ret-&gt;namep = buf + sizeof(struct name);	strcpy(ret-&gt;namep, newname);	return ret;}</pre></p><p>However,piggybacking a second regiononto a single <TT>malloc</TT> calllike thisis only portableif the second region is to be treated as an array of <TT>char</TT>.For any larger type,alignment(see questions <a href="faqcat6b6b.html?sec=struct#padding">2.12</a> and <a href="faqcat5e04.html?sec=strangeprob#ptralign">16.7</a>)becomes significant and would have to be preserved.</p><p>C99 introducesthe concept of a <a href="../../sx1/index.html#flexible array member"><dfn>flexible array member</dfn></a>,which allowsthe size of an array to be omitted if it is the last member in a structure,thusproviding a well-defined solution.</p><p>References:Rationale Sec. 3.5.4.2<br>C9X Sec. 6.5.2.1<hr><hr><hr><a name="firstclass"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/firstclass.html"><!-- qtag -->Question 2.7</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I heardthat structures could be assignedto variables and passed to and from functions, but K&amp;R1saysnot.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>What K&amp;R1 said(thoughthis was quite some time ago by now)was that the restrictions on structure operations wouldbe lifted in a forthcoming version of the compiler, and infactthe operationsofassigning structures,passing structures as function arguments,and returning structures from functionswere fully functional inRitchie'scompilereven as K&amp;R1 was being published.A few ancient compilers may have lackedthese operations,butall modern compilers support them,and they are part of the ANSI C standard,so there should be no reluctance to use them.<a href="../../struct/fn14.html" rel=subdocument>[footnote]</a></p><p>(Note that when a structure is assigned, passed, or returned,thecopying is done monolithically.This means thatthe copies of any pointer fieldswill pointto the same placeas the original.In other words,the data pointed tois <em>not</em> copied.)</p><p>See the code fragments in question <a href="faqcat973e.html?sec=fp#complex">14.11</a>for an example of structure operations in action.</p><p>References:K&amp;R1 Sec. 6.2 p. 121<br>K&amp;R2 Sec. 6.2 p. 129<br>ISO Sec. 6.1.2.5, Sec. 6.2.2.1, Sec. 6.3.16<br>H&amp;S Sec. 5.6.2 p. 133<hr><hr><hr><a name="compare"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../struct/compare.html"><!-- qtag -->Question 2.8</a></h1>

⌨️ 快捷键说明

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