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

📄 faqcat38c2.html

📁 this is a mirrored site c-faq. thought might need offline
💻 HTML
📖 第 1 页 / 共 5 页
字号:
you can improve portability,and perhaps take advantage of prewritten I/O libraries,by making use of standardized formats such asSun's XDR (RFC 1014),OSI's ASN.1(referenced in CCITT X.409and ISO&nbsp;8825``Basic Encoding Rules''),CDF, netCDF, or HDF.See alsoquestions <a href="faqcat6b6b.html?sec=struct#padding">2.12</a>, <a href="faqcat1d60.html?sec=stdio#fopenbinary">12.38</a>, and <a href="faqcat1d60.html?sec=stdio#extconform">12.42</a>.</p><p>References:PCS Sec. 6 pp. 86, 88<hr><hr><hr><a name="symtab"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../misc/symtab.html"><!-- qtag -->Question 20.6</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>If I have a <TT>char&nbsp;*</TT> variablepointing tothe name of a function,how can I call that function?Code like<pre>	extern int func(int, int);	char *funcname = "func";	int r = (*funcname)(1, 2);</pre>or<pre>	r = (*(int (*)(int, int))funcname)(1, 2);</pre>doesn't seem to work.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>By the time a program is running, information aboutthe names of its functions and variables(the``symbol table'') is no longerneeded,and may therefore not beavailable.The most straightforward thing to do,therefore,isto maintainthat information yourself,witha correspondencetable of names and function pointers:<pre>int one_func(), two_func();int red_func(), blue_func();struct { char *name; int (*funcptr)(); } symtab[] = {	"one_func",	one_func,	"two_func",	two_func,	"red_func",	red_func,	"blue_func",	blue_func,};</pre>Then,search the table for the name, and callviatheassociated function pointer,with code like this:<pre>#include &lt;stddef.h&gt;int (*findfunc(char *name))(){	int i;	for(i = 0; i &lt; sizeof(symtab) / sizeof(symtab[0]); i++) {		if(strcmp(name, symtab[i].name) == 0)			return symtab[i].funcptr;		}	return NULL;}...	char *funcname = "one_func";	int (*funcp)() = findfunc(funcname);	if(funcp != NULL)		(*funcp)();</pre>The callablefunctions should all havecompatible argument and return types.(Ideally,the function pointers would also specify the argument types.)</p><p>It issometimes possiblefor a program to read its own symbol tableif it is still present,but it must first be able to find its own executable(see question<a href="faqcatea63.html?sec=osdep#exepath">19.31</a>),and it must know how to interpret the symbol table(someUnixC libraries providean <TT>nlist</TT> function for this purpose).See also questions<a href="faqcat6b6b.html?sec=struct#fieldnames">2.15</a>,<a href="faqcatccbd.html?sec=resources#expreval">18.14</a>,and<a href="faqcatea63.html?sec=osdep#dynlink">19.36</a>.</p><p>References:PCS Sec. 11 p. 168<hr><hr><hr><a name="intovf"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../misc/intovf.html"><!-- qtag -->Question 20.6b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I ensure that integer arithmetic doesn't overflow?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The usual approach is to testthe operands against the limits inthe header file <TT>&lt;limits.h&gt;</TT>before doing the operation.For example, here is a ``careful'' addition function:<pre>intchkadd(int a, int b){	if(INT_MAX - b &lt; a) {		fputs("int overflow\n", stderr);		return INT_MAX;	}	return a + b;}</pre>See also question <a href="faqcatea63.html?sec=osdep#fpexcepts">19.39</a>.</p><p>Additional links:<a href="../../misc/sd26.html" rel=subdocument>more sample code</a><hr><hr><hr><a name="bitmanip"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../misc/bitmanip.html"><!-- qtag -->Question 20.7</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I manipulate individual bits?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Bit manipulation isstraightforwardin C,and commonly done.To extract(test)a bit,use the bitwise AND (<TT>&amp;</TT>)operator,along with a bit maskrepresenting the bit(s) you're interested in:<pre>	value &amp; 0x04</pre>To set a bit,use the bitwise OR (<TT>|</TT> or <TT>|=</TT>) operator:<pre>	value |= 0x04</pre>To clear a bit,use the bitwise complement (<TT>~</TT>)and the AND (<TT>&amp;</TT> or <TT>&amp;=</TT>) operators:<pre>	value &amp;= ~0x04</pre>(The preceding three examples all manipulatethe third-least significant,or2**2,bit,expressed as the constant bitmask <TT>0x04</TT>.)</p><p>To manipulate an arbitrary bit, use the shift-left operator(<TT>&lt;&lt;</TT>) to generate the mask you need:<pre>	value &amp; (1 &lt;&lt; bitnumber)	value |= (1 &lt;&lt; bitnumber)	value &amp;= ~(1 &lt;&lt; bitnumber)</pre>Alternatively,you may wish to precomputean array of masks:<pre>	unsigned int masks[] =		{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};	value &amp; masks[bitnumber]	value |= masks[bitnumber]	value &amp;= ~masks[bitnumber]</pre></p><p>To avoid surprises involving the sign bit,it is often a good idea to use unsigned integral typesin codewhich manipulatesbits and bytes.</p><p>See also questions <a href="faqcate034.html?sec=bool#bool2">9.2</a> and <a href="faqcat38c2.html?sec=misc#bitsets">20.8</a>.</p><p>References:K&amp;R1 Sec. 2.9 pp. 44-45<br>K&amp;R2 Sec. 2.9 pp. 48-49<br>ISO Sec. 6.3.3.3, Sec. 6.3.7, Sec. 6.3.10, Sec. 6.3.12<br>H&amp;S Sec. 7.5.5 p. 197, Sec. 7.6.3 pp. 205-6, Sec. 7.6.6 p. 210<hr><hr><hr><a name="bitsets"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../misc/bitsets.html"><!-- qtag -->Question 20.8</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I implement sets or arrays of bits?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Use arrays of <TT>char</TT> or <TT>int</TT>,with a few macros to access the desired bitin the proper cell of the array.Here are some simple macros to use with arrays of <TT>char</TT>:<pre>#include &lt;limits.h&gt;		/* for CHAR_BIT */#define BITMASK(b) (1 &lt;&lt; ((b) % CHAR_BIT))#define BITSLOT(b) ((b) / CHAR_BIT)#define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))#define BITCLEAR(a, b) ((a)[BITSLOT(b)] &amp;= ~BITMASK(b))#define BITTEST(a, b) ((a)[BITSLOT(b)] &amp; BITMASK(b))#define BITNSLOTS(nb) ((nb + CHAR_BIT - 1) / CHAR_BIT)</pre>(If you don't have <TT>&lt;limits.h&gt;</TT>,try using 8 for <TT>CHAR_BIT</TT>.)</p><p>Here are some usage examples.To declare an ``array'' of 47 bits:<pre>	char bitarray[BITNSLOTS(47)];</pre>To set the23rdbit:<pre>	BITSET(bitarray, 23);</pre>To test the35thbit:<pre>	if(BITTEST(bitarray, 35)) ...</pre>Tocompute theunion of two bit arraysand place it in a third array(with all three arrays declared as above):<pre>	for(i = 0; i &lt; BITNSLOTS(47); i++)		array3[i] = array1[i] | array2[i];</pre>To compute the intersection, use <TT>&amp;</TT> instead of <TT>|</TT>.</p><p>As a more realistic example,here is a quick implementation of the Sieve of Eratosthenes,for computingprime numbers:<pre>#include &lt;stdio.h&gt;#include &lt;string.h&gt;#define MAX 10000int main(){	char bitarray[BITNSLOTS(MAX)];	int i, j;	memset(bitarray, 0, BITNSLOTS(MAX));	for(i = 2; i &lt; MAX; i++) {		if(!BITTEST(bitarray, i)) {			printf("%d\n", i);			for(j = i + i; j &lt; MAX; j += i)				BITSET(bitarray, j);		}	}	return 0;}</pre></p><p>See also question <a href="faqcat38c2.html?sec=misc#bitmanip">20.7</a>.</p><p>Additional links:<a href="../../misc/bitsets.970425.html">further explanation</a></p><p>References:H&amp;S Sec. 7.6.7 pp. 211-216<hr><hr><hr><a name="endiantest"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../misc/endiantest.html"><!-- qtag -->Question 20.9</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I determine whether a machine'sbyte orderis big-endian or little-endian?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The usual techniques areto use a pointer:<pre>	int x = 1;	if(*(char *)&amp;x == 1)		printf("little-endian\n");	else	printf("big-endian\n");</pre>or a union:<pre>	union {		int i;		char c[sizeof(int)];	} x;	x.i = 1;	if(x.c[0] == 1)		printf("little-endian\n");	else	printf("big-endian\n");</pre></p><p>(Note that there are also byte order possibilities beyond simplebig-endian and little-endian<a href="../../misc/fn96.html" rel=subdocument>[footnote]</a>.)</p><p>See also questions <a href="faqcat204f.html?sec=cpp#ifendian">10.16</a>and <a href="faqcat38c2.html?sec=misc#byteswap">20.9b</a>.</p><p>References:H&amp;S Sec. 6.1.2 pp. 163-4<hr><hr><hr><a name="byteswap"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../misc/byteswap.html"><!-- qtag -->Question 20.9b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How do I swap bytes?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>V7 Unix had a <TT>swab</TT> function,but it seems to have been forgotten.</p><p>A problem withexplicit byte-swapping codeis that you haveto decide whether to call it or not,based on the byte order of the dataand the byte order of the machine in use.Question<a href="faqcat38c2.html?sec=misc#endiantest">20.9</a>shows how, but it's a nuisance.</p><p>A better solution is todefine functionswhich convert between the known byte order of the dataand the (unknown) byte order of the machinein use,and to arrange for these functions to be no-opson those machines which already match the desired byte order.A set of such functions,introduced with the BSD networking code but now in wide use,is <TT>ntohs</TT>, <TT>htons</TT>, <TT>ntohl</TT>, and <TT>htonl</TT>.These are intended to convert between``network'' and ``host'' byte orders,for ``short'' or ``long'' integers,where ``network'' order is always big-endian,and where ``short'' integers are always 16 bitsand ``long'' integers are 32 bits.(This is not the C definition, of course,but it's compatible with the C definition;see question <a href="faqcatd3c2.html?sec=decl#inttypes">1.1</a>.)So if you know that the data you want to convert from or to is big-endian,you can use these functions.(The point is that you <em>always</em> call the functions,making your code much cleaner.Each function either swaps bytes if it has to, or does nothing.The decision to swap or not to swap gets made once,when the functions are implemented for a particular machine,rather than being made many times in many different calling programs.)</p><p>If you do have to write your own byte-swapping code,the two obvious approaches are again to use pointers or unions,as in question <a href="faqcat38c2.html?sec=misc#endiantest">20.9</a>.Here is an example using pointers:<pre>void byteswap(char *ptr, int nwords){	char *p = ptr;	while(nwords-- &gt; 0) {		char tmp = *p;		*p = *(p + 1);		*(p + 1) = tmp;		p += 2;	}}</pre></p><p>And here is one using unions:<pre>union word	{	short int word;	char halves[2];	};void byteswap(char *ptr, int nwords){	register union word *wp = (union word *)ptr;	while(nwords-- &gt; 0) {		char tmp = wp-&gt;halves[0];		wp-&gt;halves[0] = wp-&gt;halves[1];		wp-&gt;halves[1] = tmp;		wp++;	}}</pre></p><p>These functions swap two-byte quantities;the extension to fouror morebytes should be obvious.The union-using code is imperfectin that it assumes that the passed-in pointer is word-aligned.It would also be possible to write functionsaccepting separate source and destination pointers,or accepting single words and returning the swapped values.</p>

⌨️ 快捷键说明

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