📄 faqcat6b6b.html
字号:
<p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Is there a way tocompare structuresautomatically?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>No.There isnot agoodwayfor a compiler to implementstructurecomparison(i.e. to support the <TT>==</TT> operator for structures)which is consistent with C's low-level flavor.Asimplebyte-by-byte comparison couldfounder onrandom bitspresent in unused ``holes'' in the structure(such padding is usedto keep the alignment of later fields correct;seequestion<a href="faqcat6b6b.html?sec=struct#padding">2.12</a>).A field-by-field comparison might require unacceptable amounts ofrepetitivecode for large structures.Anycompiler-generatedcomparisoncould not be expectedto compare pointerfieldsappropriatelyin all cases:for example,it's often appropriate to compare <TT>char *</TT>fieldswith <TT>strcmp</TT> rather than <TT>==</TT>(see also question <a href="faqcate107.html?sec=charstring#stringeq">8.2</a>).</p><p>If youneedto compare two structures,you'll have towrite your own function to do so,field by field.</p><p>References:K&R2 Sec. 6.2 p. 129<br>Rationale Sec. 3.3.9<br>H&S Sec. 5.6.2 p. 133<hr><hr><hr><a name="passret"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../struct/passret.html"><!-- qtag -->Question 2.9</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Howarestructure passing and returningimplemented?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>When structures are passed as arguments to functions,the entire structure is typically pushed on the stack,using as many words as are required.(Programmers often choose to usepointers to structures instead,precisely to avoid this overhead.)Some compilersmerelypass a pointerto the structure,though they may have to make a local copyto preservepass-by-valuesemantics.</p><p>Structures are often returned from functionsin a location pointed to by an extra,compiler-supplied``hidden'' argumentto the function.Some older compilers used a special, static location for structure returns,although this made structure-valued functionsnon-reentrant,which ANSI C disallows.</p><p>References:ISO Sec. 5.2.3<hr><hr><hr><a name="anonstruct"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../struct/anonstruct.html"><!-- qtag -->Question 2.10</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How canI pass constant values to functions which accept structure arguments?How can I create nameless, immediate, constant structure values?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Traditional C had no way of generating anonymous structure values;you had to use a temporary structure variableora little structure-building function;see question <a href="faqcat973e.html?sec=fp#complex">14.11</a> for an example.</p><p>C99 introduces ``compound literals'',one form of whichprovides forstructure constants.For example, to pass a constant coordinate pairto ahypothetical<TT>plotpoint</TT> functionwhich expects a <TT>struct point</TT>,you can call<pre> plotpoint((struct point){1, 2});</pre>Combined with ``designated initializers''(another C99 feature),it is also possible to specify member values by name:<pre> plotpoint((struct point){.x=1, .y=2});</pre></p><p>See also question <a href="faqcatabdc.html?sec=ptrs#refconst">4.10</a>.</p><p>References:C9X Sec. 6.3.2.5, Sec. 6.5.8<hr><hr><hr><a name="io"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../struct/io.html"><!-- qtag -->Question 2.11</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I read/write structures from/todata files?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It is relatively straightforwardto write a structureoutusing <TT>fwrite</TT>:<pre> fwrite(&somestruct, sizeof somestruct, 1, fp);</pre>and a corresponding<TT>fread</TT> invocation can read it back in.What happens here is that<TT>fwrite</TT> receives a pointer to the structure,and writes(or <TT>fread</TT> correspondingly reads)the memory image of the structureas a stream of bytes.The <TT>sizeof</TT> operator determineshow many bytes the structure occupies.</p><p>(Thecall to <TT>fwrite</TT> above is correctunder an ANSI compileras long as a prototype for <TT>fwrite</TT> is in scope,usually because <TT><stdio.h></TT> is <TT>#include</TT>d.</p><p>However,data fileswrittenas memory imagesin this waywill<em>not</em>beportable,particularlyif they contain floating-point fields or pointers.The memory layout of structures ismachine andcompiler dependent.Different compilers may use different amounts of padding(see question <a href="faqcat6b6b.html?sec=struct#padding">2.12</a>),andthe sizes and byte orders of fundamental typesvary across machines.Therefore,structures written as memory imagescannot necessarily be read back inby programs running on other machines(or even compiled by other compilers),and this is animportant concern ifthe data files you're writingwill ever be interchanged between machines.See alsoquestions<a href="faqcat6b6b.html?sec=struct#padding">2.12</a>and<a href="faqcat38c2.html?sec=misc#binaryfiles">20.5</a>.</p><p>Also,if the structure contains any pointers(<TT>char *</TT> strings,or pointers to other data structures),only the pointer values will be written,and they are most unlikely to be valid when read back in.Finally,notethatfor widespread portabilityyou must use the <TT>"b"</TT> flagwhen opening the files;see question <a href="faqcat1d60.html?sec=stdio#fopenbinary">12.38</a>.</p><p>A more portable solution,though it's a bit more work initially,is to write a pair of functionsfor writing and reading a structure,field-by-field,in a portable(perhaps even human-readable)way.</p><p>References:H&S Sec. 15.13 p. 381<hr><hr><hr><a name="padding"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../struct/padding.html"><!-- qtag -->Question 2.12</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why is mycompilerleaving holes in structures,wasting spaceand preventing``binary'' I/O to external datafiles?CanI turnthisoff,or otherwise control the alignment of structure fields?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Many machinesaccess values in memorymost efficientlywhen the values are appropriately aligned.(For example,on a byte-addressed machine,<TT>short int</TT>s of size 2might best be placed at even addresses,and<TT>long int</TT>s of size 4at addresses which are a multiple of 4.)Some machines cannot perform unaligned accessesat all,and<em>require</em> thatall databe appropriately aligned.</p><p>Therefore, if you declare a structure like<pre> struct { char c; int i; };</pre>the compiler will usuallyleave an unnamed, unused holebetween the <TT>char</TT> and <TT>int</TT> fields,to ensure that the<TT>int</TT> fieldis properly aligned.(This incremental alignment of the second fieldbased on the firstrelies on the factthat the structure itselfis always properly aligned,with the most conservativealignment requirement.The compiler guarantees this alignment for structures it allocates,as does <TT>malloc</TT>.)</p><p>Your compiler may provide an extension to give youcontrolover the packing of structures(i.e. whether they are padded or not),perhapswitha <TT>#pragma</TT> (seequestion <a href="faqcat7d4b.html?sec=ansi#pragma">11.20</a>),but thereis no standard method.</p><p>If you're worried about wasted space,you can minimize the effects of paddingby ordering the members ofastructurebased on their base types,from largest to smallest.You can sometimes get more control over size and alignmentby using bit-fields,although theyhave their own drawbacks.(See question <a href="faqcat6b6b.html?sec=struct#bitfields">2.26</a>.)</p><p>See alsoquestions <a href="faqcat6b6b.html?sec=struct#endpad">2.13</a>, <a href="faqcat5e04.html?sec=strangeprob#ptralign">16.7</a>, and <a href="faqcat38c2.html?sec=misc#binaryfiles">20.5</a>.</p><p>Additional links:<br><br>A bit more<a href="faqcat6b6b.html?sec=struct#align">explanation of ``alignment''</a>and why it requires paddding<br><br>Additional<a href="../../struct/align.esr.html">ideas on working with alignment and padding</a>by Eric Raymond,couched in the form of six new FAQ list questions<br><br>Corrections to the above from<a href="../../struct/align.esr2.html">Norm Diamond</a>and<a href="../../struct/align.esr3.html">Clive Feather</a></p><p>References:K&R2 Sec. 6.4 p. 138<br>H&S Sec. 5.6.4 p. 135<hr><hr><hr><a name="endpad"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../struct/endpad.html"><!-- qtag -->Question 2.13</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why does <TT>sizeof</TT> report a larger size than I expect for astructure type,as if there were padding at the end?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Padding at the end of a structure may be necessaryto preserve alignmentwhen an array of contiguous structures is allocated.Evenwhenthe structure is not part of an array,thepadding remains,so that <TT>sizeof</TT> can always return a consistentsize.See also question<a href="faqcat6b6b.html?sec=struct#padding">2.12</a>.</p><p>References:H&S Sec. 5.6.7 pp. 139-40<hr><hr><hr><a name="offsetof"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../struct/offsetof.html"><!-- qtag -->Question 2.14</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I determine the byte offset of a field within a structure?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>ANSI C defines the <TT>offsetof()</TT> macroin <TT><stddef.h></TT>,which lets you computethe offset of field <TT>f</TT> in struct <TT>s</TT>as<TT>offsetof(struct s, f)</TT>.If for some reason you have to code this sort of thing yourself,one possibility is<pre> #define offsetof(type, f) ((size_t) \ ((char *)&((type *)0)->f - (char *)(type *)0))</pre></p><p>This implementation is not 100% portable;some compilers may legitimately refuse to accept it.</p><p>(The complexitiesofthe definition abovebear a bit of explanation.The subtraction of a carefully converted null pointerissupposedto guaranteethat a simple offset is computedeven if the internal representation of the null pointeris not 0.The casts to <TT>(char *)</TT> arrangethat the offsetso computedis a byte offset.The nonportability is in pretending,if only for the purposes of address calculation,that there is an instance of the <TT>type</TT> sitting at address 0.Note, however,that since the pretend instance is not actually referenced,an access violation is unlikely.)</p><p>References:ISO Sec. 7.1.6<br>Rationale Sec. 3.5.4.2<br>H&S Sec. 11.1 pp. 292-3<hr><hr><hr><a name="fieldnames"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../struct/fieldnames.html"><!-- qtag -->Question 2.15</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I access structure fields by name at run time?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Keep trackof the fieldoffsets as computedusing the <TT>offsetof()</TT> macro(see question <a href="faqcat6b6b.html?sec=struct#offsetof">2.14</a>).If <TT>structp</TT> is a pointer toan instance of the structure,and field <TT>f</TT> is an <TT>int</TT>having offset <TT>offsetf</TT>,<TT>f</TT>'s value can be set indirectly with<pre>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -