📄 http:^^www.cs.wisc.edu^~glew^coding-standards.html
字号:
<P><H3>Use of 'indent'</H3>It is possible to use the program, <B>indent</B>,to provide formatting of a file that<I>roughly</I>conformsto these coding standards (with some incompatible differences).To accomplish this, run:<PRE><CODE> indent <I>in_file</I> -npro -nip -nfc1 -cli0.5 -c0 -i8</CODE></PRE>This will save the old version of the file in <CODE><I>in_file</I>.BAK</CODE>and place the newly-formatted version in <CODE><I>in_file</I></CODE>(or you can specify an explicit <CODE><I>out_file</I></CODE> after <CODE><I>in_file</I></CODE>).Unfortunately, it does not handle formatting of comments correctly in all cases.In specific,comments of the form:<PRE>/* Very boring comment that goes beyond the end of the line (length = 76) */</PRE>will get reformatted to be:<PRE> <CODE>/* Very boring comment that goes beyond the end of the line * (length = 76) */</CODE></PRE>in direct violation of the comment standard.What this means is thatafter running <CODE>indent</CODE> on a file,it is still necessary to go through the file and edit itto ensure that it conforms to the coding standards.<H3>Use of 'lint'</H3>It is important to remember that <B>C</B> takes the point of viewthat programmers know what they're doing.Luckily for the programmers,tools have been developed which aid them in helping ensurethat what they did was what they intended.One of the more useful tools along these lines is <CODE>lint</CODE>.The <CODE>lint</CODE> command checks <B>C</B> code for coding and syntax errors,and for inefficient or non-portable code.This includes such things as detection of unused(or potential problems with)variables and functions,type mismatches,possible errors in flow control,and legal constructions that may not be what were intended.The details of <CODE>lint</CODE>'s operation differ from machine to machine,so the reader is referred to the "<CODE>man</CODE>" page for <CODE>lint</CODE>for more particulars on this command.<H2>Example</H2>The following is an example intended to demonstrate some of the above standards.<PRE>/* * is_cache_hit * *FUNCTION: * This routine determines whether a memory reference is a cache hit. If it is, * "*index_p" will be changed to refer to the appropriate element in the cache and * TRUE will be returned. If not, "*index_p" will be modified to refer to the * element in the cache to be replaced and FALSE will be returned. * *LOGIC: * The appropriate cache is selected. Based upon the type of the cache, the cache * is searched to determine if the address in question ("mem_addr") is present. * If so, that cache index is the one to return to the caller (via index_p). * If not, the cache index to be returned to the user (for potential modification) * is determined, again, based upon the cache type. * *ASSUMPTIONS: * Assumes the selected cache is configured. * *NOTE: * Special circumstances/cautions. * Only direct-mapped and fully-associative caches are currently supported. * Unspecified results will be returned when an unsupported cache type is specified. * *RETURNS: * TRUE - element is in the cache. * FALSE - element is not in the cache. */boolis_cache_hit(mem_addr, index_p, selector, knobs)mo_addr mem_addr; /* memory address */int *index_p; /* OUT - pointer to cache index for hit or replacement */int selector; /* selects the cache in question (instruction or data) */knobs_t knobs; /* system configuration parameters/constraints (ptr) */{ int index; /* Used for local index computations. */ dfa_cache_elem *cache; /* Cache pointer. */ /* Select the cache to be used. */ cache = &dfa_cache[selector][0]; /* * We direct our cache pointer at the first element of the desired cache. * We can now simply reference it using "cache". */ /* Determine the cache type and operate accordingly. */ switch (knobs->cache_type[selector]) { case DIRECT_MAP: index = mem_addr & cache_index_mask[selector]; if ( cache[index].valid && (cache[index].tab == mem_addr)) { /* This is a HIT! */ *index_p = index; return TRUE; } else { /* This is a MISS! */ *index_p = index; return FALSE; } break; case ASSOCIATIVE: case FULLY_ASSOCIATIVE: /* Step through cache looking for match. */ for ( index = 0; index <= knobs->cache_size[selector] ; index ++) { if ( cache[index].valid && (cache[index].tab == mem_addr)) { /* This is a HIT! */ *index_p = index; return TRUE; } } /* No match found. We have a MISS! Find a free index. */ *index_p = Get_LRU_index(selector, knobs); return FALSE; break; case SET_ASSOCIATIVE: case SET_ASSOCIATIVE_4: case SET_ASSOCIATIVE_8: if (debug > 1) warning("Unimplemented cache type in 'is_cache_hit()'"); break; default: fatal("Unexpected default in 'is_cache_hit()'"); }}/*** end is_cache_hit() ***/</PRE><H2> APPENDIX: P6 System Header File </H2>The following is a listing of the <CODE>p6system.h</CODE> header fileas of December 13, 1991.For the most accurate rendition of this file,the reader is referred to <CODE>~p6/arch/include</CODE>where the most current copy should be available.<PRE>/* Copyright Intel Corporation, 1991. */#ifndef lintstatic char *rcsid_p6system_h = "$Header: /u/g/l/glew/public/html/RCS/coding-standards.html,v 1.2 1995/06/22 08:43:54 glew Exp $";#endif/* * /p6/arch/include/p6system.h * * P6 standard C header file * * This file contains definitions that should be useful in C programming * throughout the P6 project. * * The recommended use of each definition or declaration given below is * documented, and should be respected so as to improve the readability of * your C code. (i.e. don't use something contained herein in a way that is * not documented, because it will tend to obscure your code from other P6 * members. * */#ifndef _P6SYSTEM_H_#define _P6SYSTEM_H_/* * Standard truth values * * Realize that because C declares all non-zero values to be "true", you * should never write code like "if (a == TRUE)". The recommended code would * instead simply read "if (a)". * * Direct comparison with FALSE is acceptable, though, because * "if (A == FALSE)" both conveys its intended meaning, and doesn't have the * got-yas of the comparisons with TRUE. * * Also try to be conscience of the different between FALSE and NULL. FALSE * denotes a boolean value, whereas NULL is a pointer value. Don't compare * pointers with FALSE; use NULL instead. Similarly, use FALSE if you're * testing a boolean. * */#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif/* * Standard "boolean" type. * * Although C has little concept of an actual "boolean" type (TRUE/FALSE), * variables that are, in fact, booleans are best indicated as such * by the use of such a type. To that end, the type is provided here. * */typedef int bool;/* * ANSI C compatible function prototyping... * * ANSI C compilers will perform type checking on arguments passed to * functions when a function prototype for that function is provided * (presumably in a header file). Unfortunately, K&R C compilers (i.e. the * olders ones) consider ANSI function prototypes to be syntax errors. This * macro is designed to deal with this. * * Currently, C compilers which understand function prototypes are available * on the RS/6000 as xlc and c89, on the suns and vaxes as gcc. * * ANSI C prototypes and a K&R declaration for the libc function strncpy * follow: * * / * ANSI C function prototype * / * extern char *strncpy(char *, char *, unsigned); * * / * Alternate ANSI C function prototype * / * extern char *strncpy(char *dst, char *src, unsigned max_length); * * / * K&R function prototype * / * extern char *strncpy(); * * ANSI C compilers will accept any of the above three syntaxes. The second * is considered to be a more descriptive prototype, and its use is * encouraged. * * The problem is that K&R compilers still exist, and we want to be able to * compile our programs on them. The macro give below uses the ANSI C declared * preprocessor symbol __STDC__ to detect whether the compiler can understand * function prototypes or not. If __STDC__ is not declared, then the * prototype is omitted. * * An example of how to use this macro is given below: * ***** * USAGE ***** * * / * Recommended declaration for libc's strncpy * / * extern char *strncpy ARGS((char *dst, char *src, unsigned max_length)); * * Notice the double set of parentheses. These ARE REQUIRED. * * If __STDC__ is defined (which is done automatically by ANSI C compilers), * then this expands to: * * extern char *strncpy (char *dst, char *src, unsigned max_length); * * Otherwise, it expands to: * * extern char *strncpy (); * * This gives us the functionality we want, which is that, given an ANSI C * compiler, we will get argument type checking, but our code will still work * on older K&R compilers. */#ifndef ARGS#ifdef __STDC__#define ARGS(x) x#else#define ARGS(x) ()#endif#endif ARGS/* * Assertions * * It is common and useful programming practice to add assertions to your * code, so that events which are either unexpected or unhandled by the * current code will be trapped, rather than quietly creating bugs further * along the line. * * P6 code should use the following macro when coding such assertions, thus * allowing for a single, uniform mechanism. (Unfortunately, nearly every * machine implements its own version of assertions, thus necessitating us to * use own so as to get a uniform interface.) * * P6 assertions are coded as follows: * ***** * USAGE ***** * * / * foo should never be greater than 7 * / * ASSERT(foo <= 7, ("foo took on unexpected value %d", foo)); * * Notice the second set of parentheses. These ARE REQUIRED. They surround an * argument list that will effectively be passed to printf (except that it * will print on stderr instead of stdout). * * The first argument to the ASSERT macro is checked for to see if it is true. * This is the expression that we say is being asserted. The second argument * is really a parenthenized list of arguments to pass to printf in the case * that the assert fails. It is generally helpful to put an informative * message here, including any variables or values which might help indicate * why the assert failed. * * Assertion failure is always fatal. A failed assertion never returns. It * exits with status = 1. * * This macro expands into a function call to the routine _p6_assert, which is * defined in the library /p6/arch/lib/{p6hosttype}/libp6.a. This library can * be linked with the CC command line arguments "-L/p6/arch/lib/`p6hosttype`" * and "-lp6". * * This can be helpful in a debugger: set a breakpoint in _p6_assert. Then, * if an assertion is triggered, you will hit the breakpoint before the * program exits, and you can examine program values on the stack and such. * * The omitASSERT macro is purely a syntactic convenience. It expands to * nothing, providing an easy way to "comment out" an assertion. * * If the preprocessor symbol NOASSERTS is defined, then ASSERT expands to * nothing, as well, providing an easy way to run without assertion checking. */#ifdef NOASSERTS#define ASSERT(x, args)#else /* NODEBUG no set */extern void _p6_assert_setup ARGS((int debug, char *file, unsigned lineno));/*VARARGS1*/extern void _p6_assert ARGS((char *format, ...));#define ASSERT(x, args) { \ if (!(x)) { \ _p6_assert_setup(0, 0, __FILE__, __LINE__); \ _p6_assert args ; \ } \}#endif#define omitASSERT(x, args)/* * The macro DEBUGF prints a debugging message to the stderr (or optionally any * (FILE *) the user specifies). It also takes printf style arguments, ala: * ***** * USAGE ***** * * / * print informative debugging message * / * DEBUGF(("This is the value of foo: %d\n", foo)); * * To enable DEBUGF, the user must have #define'd the preprocessor symbol * DEBUG before including this file. If DEBUG has not been defined, then * DEBUGF expands to nothing (i.e. there is no debugging code in the object * file). * * To redirect the output of DEBUGF, the user can redefine the preprocessor * symbol DEBUGF_OUT. For example, to redirect to stdout: * * #include <I>stdio.h</I> * #define DEBUG * #include <I>p6system.h</I> * #undef DEBUGF_OUT * #define DEBUGF_OUT stdout * * DEBUGF outputs its messages conditional on another preprocessor symbol, * DEBUGF_COND. To be able to turn debugging messages on and off at runtime: * * #define DEBUG * #include <I>p6system.h</I> * #undef DEBUGF_COND * int DebugVar = 0; / * Defaults to no debugging messages * / * #define DEBUGF_COND DebugVar * * Then, debugging output is conditional on the variable DebugVar. * * The macro omitDEBUGF is similar to omitASSERT, above. It expands to * nothing, making it easy to "comment out" a DEBUG message. * * Giving credit where credit is due, nearly all of these ideas are stolen * directly from Andy Glew's standard debug.h file. */ #ifdef DEBUG#define DEBUGF(args) { \ if (DEBUGF_COND) { \ _p6_assert_setup(1, DEBUGF_OUT, __FILE__, __LINE__); \ _p6_assert args ; \ } \}#else /* not DEBUG */#define DEBUGF(args)#endif /* DEBUG */#define DEBUGF_OUT 0#define DEBUGF_COND 1#define omitDEBUGF(args)/* * Standard "safe" versions of malloc, realloc, and calloc * * Typically, programmers either clutter their code with checks for a NULL * return value after every call to malloc, or they omit such checks * altogether. These routines are available in the p6 library, and should be * used as general replacements to malloc and family. This routines do the * NULL themselves. They guarantee to return a valid pointer for the amount * of memory requested. If the underlying malloc() etc actually failed to * return the memory (i.e. returned NULL), these routines exit with a message * to stderr explaining the situation (via an ASSERT, for above), rather than * returning. * * These functions are defined in /p6/arch/lib/{p6hosttype}/libp6.a. This * library can be linked with the CC command line arguments * "-L/p6/arch/lib/`p6hosttype`" and "-lp6". * * Using these routines simply eliminates the error checking from the * programmer's code, thus improving readability. * */extern char *xmalloc ARGS((unsigned size));extern char *xrealloc ARGS((char *pointer, unsigned size));extern char *xcalloc ARGS((unsigned nelem, unsigned elsize));#endif /* ifndef _P6SYSTEM_H_ */</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -