📄 subject_19421.htm
字号:
<br>内容:一篇 c faq:<BR>摘自 google newsgroup:<BR>This article is Copyright 1990-1999 by Steve Summit. Content from the<BR>book _C Programming FAQs: Frequently Asked Questions_ is made available<BR>here by permission of the author and the publisher as a service to the<BR>community. It is intended to complement the use of the published text<BR>and is protected by international copyright laws. The content is made<BR>available here and may be accessed freely for personal use but may not<BR>be republished without permission.<BR><BR>This article contains minimal answers to the comp.lang.c frequently-<BR>asked questions list. More detailed explanations and references can be<BR>found in the long version (posted on the first of each month, or see<BR>question 20.40 for availability), and in the web version at http://www.eskimo.com/~scs/C-faq/top.html<BR>, and in the book _C Programming FAQs: Frequently Asked Questions_<BR>(Addison-Wesley, 1996, ISBN 0-201-84519-9). <BR><BR>Section 1. Declarations and Initializations<BR><BR>1.1: How do you decide which integer type to use?<BR><BR>A: If you might need large values (tens of thousands), use long.<BR> Otherwise, if space is very important, use short. Otherwise,<BR> use int.<BR><BR>1.4: What should the 64-bit type on a machine that can support it?<BR><BR>A: C9X specifies long long.<BR><BR>1.7: What's the best way to declare and define global variables?<BR><BR>A: The best arrangement is to place each definition in some<BR> relevant .c file, with an external declaration in a header file.<BR><BR>1.11: What does extern mean in a function declaration?<BR><BR>A: Nothing, really; the keyword extern is optional here.<BR><BR>1.12: What's the auto keyword good for?<BR><BR>A: Nothing.<BR><BR>1.14: I can't seem to define a linked list node which contains a<BR> pointer to itself.<BR><BR>A: Structures in C can certainly contain pointers to themselves;<BR> the discussion and example in section 6.5 of K&R make this<BR> clear. Problems arise if an attempt is made to define (and use)<BR> a typedef in the midst of such a declaration; avoid this.<BR><BR>1.21: How do I declare an array of N pointers to functions returning<BR> pointers to functions returning pointers to characters?<BR><BR>A: char *(*(*a[N])())();<BR> Using a chain of typedefs, or the cdecl program, makes these<BR> declarations easier.<BR><BR>1.22: How can I declare a function that returns a pointer to a<BR> function of its own type?<BR><BR>A: You can't quite do it directly. Use a cast, or wrap a struct<BR> around the pointer and return that.<BR><BR>1.25: My compiler is complaining about an invalid redeclaration of a<BR> function, but I only define it once.<BR><BR>A: Calling an undeclared function declares it implicitly as<BR> returning int.<BR><BR>1.25b: What's the right declaration for main()?<BR><BR>A: See questions 11.12a to 11.15.<BR><BR>1.30: What am I allowed to assume about the initial values<BR> of variables which are not explicitly initialized?<BR><BR>A: Uninitialized variables with "static" duration start out as 0,<BR> as if the programmer had initialized them. Variables with<BR> "automatic" duration, and dynamically-allocated memory, start<BR> out containing garbage (with the exception of calloc).<BR><BR>1.31: Why can't I initialize a local array with a string?<BR><BR>A: Perhaps you have a pre-ANSI compiler.<BR><BR>1.31b: What's wrong with "char *p = malloc(10);" ?<BR><BR>A: Function calls are not allowed in initializers for global or<BR> static variables.<BR><BR>1.32: What is the difference between char a[] = "string"; and<BR> char *p = "string"; ?<BR><BR>A: The first declares an initialized and modifiable array; the<BR> second declares a pointer initialized to a not-necessarily-<BR> modifiable constant string.<BR><BR>1.34: How do I initialize a pointer to a function?<BR><BR>A: Use something like "extern int func(); int (*fp)() = func;" .<BR><BR><BR>Section 2. Structures, Unions, and Enumerations<BR><BR>2.1: What's the difference between struct x1 { ... }; and<BR> typedef struct { ... } x2; ?<BR><BR>A: The first structure is named by a tag, the second by a typedef<BR> name.<BR><BR>2.2: Why doesn't "struct x { ... }; x thestruct;" work?<BR><BR>A: C is not C++.<BR><BR>2.3: Can a structure contain a pointer to itself?<BR><BR>A: See question 1.14.<BR><BR>2.4: What's the best way of implementing opaque (abstract) data types<BR> in C?<BR><BR>A: One good way is to use structure pointers which point to<BR> structure types which are not publicly defined.<BR><BR>2.6: I came across some code that declared a structure with the last<BR> member an array of one element, and then did some tricky<BR> allocation to make it act like the array had several elements.<BR> Is this legal or portable?<BR><BR>A: An official interpretation has deemed that it is not strictly<BR> conforming with the C Standard.<BR><BR>2.7: I heard that structures could be assigned to variables and<BR> passed to and from functions, but K&R1 says not.<BR><BR>A: These operations are supported by all modern compilers.<BR><BR>2.8: Is there a way to compare structures automatically?<BR><BR>A: No.<BR><BR>2.10: Can I pass constant values to functions which accept structure<BR> arguments?<BR><BR>A: Not yet. As of this writing, C has no way of generating<BR> anonymous structure values.<BR><BR>2.11: How can I read/write structures from/to data files?<BR><BR>A: It is relatively straightforward to use fread and fwrite.<BR><BR>2.12: How can I turn off structure padding?<BR><BR>A: There is no standard method.<BR><BR>2.13: Why does sizeof report a larger size than I expect for a<BR> structure type?<BR><BR>A: The alignment of arrays of structures must be preserved.<BR><BR>2.14: How can I determine the byte offset of a field within a<BR> structure?<BR><BR>A: ANSI C defines the offsetof() macro, which should be used if<BR> available.<BR><BR>2.15: How can I access structure fields by name at run time?<BR><BR>A: Build a table of names and offsets, using the offsetof() macro.<BR><BR>2.18: I have a program which works correctly, but dumps core after it<BR> finishes. Why?<BR><BR>A: Check to see if a structure type declaration just before main()<BR> is missing its trailing semicolon, causing main() to be declared<BR> as returning a structure. See also questions 10.9 and 16.4.<BR><BR>2.20: Can I initialize unions?<BR><BR>A: The current C Standard allows an initializer for the first-named<BR> member.<BR><BR>2.22: What is the difference between an enumeration and a set of<BR> preprocessor #defines?<BR><BR>A: At the present time, there is little difference. The C Standard<BR> states that enumerations are compatible with integral types.<BR><BR>2.24: Is there an easy way to print enumeration values symbolically?<BR><BR>A: No.<BR><BR><BR>Section 3. Expressions<BR><BR>3.1: Why doesn't the code "a[i] = i++;" work?<BR><BR>A: The variable i is both referenced and modified in the same<BR> expression.<BR><BR>3.2: Under my compiler, the code "int i = 7;<BR> printf("%d\n", i++ * i++);" prints 49. Regardless of the order<BR> of evaluation, shouldn't it print 56?<BR><BR>A: The operations implied by the postincrement and postdecrement<BR> operators ++ and -- are performed at some time after the<BR> operand's former values are yielded and before the end of the<BR> expression, but not necessarily immediately after, or before<BR> other parts of the expression are evaluated.<BR><BR>3.3: What should the code "int i = 3; i = i++;" do?<BR><BR>A: The expression is undefined.<BR><BR>3.3b: Here's a slick expression: "a ^= b ^= a ^= b". It swaps a and b<BR> without using a temporary.<BR><BR>A: Not portably; its behavior is undefined.<BR><BR>3.4: Don't precedence and parentheses dictate order of evaluation?<BR><BR>A: Operator precedence and explicit parentheses impose only a<BR> partial ordering on the evaluation of an expression, which does<BR> not generally include the order of side effects.<BR><BR>3.5: But what about the && and || operators?<BR><BR>A: There is a special exception for those operators: left-to-right<BR> evaluation is guaranteed.<BR><BR>3.8: What's a "sequence point"?<BR><BR>A: A point (at the end of a full expression, or at the ||, &&, ?:,<BR> or comma operators, or just before a function call) at which all<BR> side effects are guaranteed to be complete.<BR><BR>3.9: So given a[i] = i++; we don't know which cell of a[] gets<BR> written to, but i does get incremented by one, right?<BR><BR>A: *No*. Once an expression or program becomes undefined, *all*<BR> aspects of it become undefined.<BR><BR>3.12: If I'm not using the value of the expression, should I use i++<BR> or ++i to increment a variable?<BR><BR>A: Since the two forms differ only in the value yielded, they are<BR> entirely equivalent when only their side effect is needed.<BR><BR>3.14: Why doesn't the code "int a = 1000, b = 1000;<BR> long int c = a * b;" work?<BR><BR>A: You must manually cast one of the operands to (long).<BR><BR>3.16: Can I use ?: on the left-hand side of an assignment expression?<BR><BR>A: No.<BR><BR><BR>Section 4. Pointers<BR><BR>4.2: What's wrong with "char *p; *p = malloc(10);"?<BR><BR>A: The pointer you declared is p, not *p.<BR><BR>4.3: Does *p++ increment p, or what it points to?<BR><BR>A: *p++ increments p. To increment the value pointed to by p, use<BR> (*p)++ .<BR><BR>4.5: I want to use a char * pointer to step over some ints. Why<BR> doesn't "((int *)p)++;" work?<BR><BR>A: In C, a cast operator is a conversion operator, and by<BR> definition it yields an rvalue, which cannot be assigned to, or<BR> incremented with ++.<BR><BR>4.8: I have a function which accepts, and is supposed to initialize,<BR> a pointer, but the pointer in the caller remains unchanged.<BR><BR>A: The called function probably altered only the passed copy of the<BR> pointer.<BR><BR>4.9: Can I use a void ** pointer as a parameter so that a function<BR> can accept a generic pointer by reference?<BR><BR>A: Not portably.<BR><BR>4.10: I have a function which accepts a pointer to an int. How can I<BR> pass a constant like 5 to it?<BR><BR>A: You will have to declare a temporary variable.<BR><BR>4.11: Does C even have "pass by reference"?<BR><BR>A: Not really, though it can be simulated.<BR><BR>4.12: I've seen different methods used for calling functions via<BR> pointers.<BR><BR>A: The extra parentheses and explicit * are now officially<BR> optional, although some older implementations require them.<BR><BR><BR>Section 5. Null Pointers<BR><BR>5.1: What is this infamous null pointer, anyway?<BR><BR>A: For each pointer type, there is a special value -- the "null<BR> pointer" -- which is distinguishable from all other pointer<BR> values and which is not the address of any object or function.<BR><BR>5.2: How do I get a null pointer in my programs?<BR><BR>A: A constant 0 in a pointer context is converted into a null<BR> pointer at compile time. A "pointer context" is an<BR> initialization, assignment, or comparison with one side a<BR> variable or expression of pointer type, and (in ANSI standard C)<BR> a function argument which has a prototype in scope declaring a<BR> certain parameter as being of pointer type. In other contexts<BR> (function arguments without prototypes, or in the variable part<BR> of variadic function calls) a constant 0 with an appropriate<BR> explicit cast is required.<BR><BR>5.3: Is the abbreviated pointer comparison "if(p)" to test for non-<BR> null pointers valid?<BR><BR>A: Yes. The construction "if(p)" works, regardless of the internal<BR> representation of null pointers, because the compiler<BR> essentially rewrites it as "if(p != 0)" and goes on to convert 0<BR> into the correct null pointer.<BR><BR>5.4: What is NULL and how is it #defined?<BR><BR>A: NULL is simply a preprocessor macro, #defined as 0 (or<BR> ((void *)0)), which is used (as a stylistic convention, in<BR> preference to unadorned 0's) to generate null pointers.<BR><BR>5.5: How should NULL be defined on a machine which uses a nonzero bit<BR> pattern as the internal representation of a null pointer?<BR><BR>A: The same as on any other machine: as 0. (The compiler makes the<BR> translation, upon seeing a 0, not the preprocessor; see also<BR> question 5.4.)<BR><BR>5.6: If NULL were defined as "((char *)0)," wouldn't that make<BR> function calls which pass an uncast NULL work?<BR><BR>A: Not in general. The complication is that there are machines<BR> which use different internal representations for pointers to<BR> different types of data. A cast is still required to tell the<BR> compiler which kind of null pointer is required, since it may be<BR> different from (char *)0.<BR><BR>5.9: If NULL and 0 are equivalent as null pointer constants, which<BR> should I use?<BR><BR>A: Either; the distinction is entirely stylistic.<BR><BR>5.10: But wouldn't it be better to use NULL, in case the value of NULL<BR> changes?<BR><BR>A: No. NULL is a constant zero, so a constant zero is equally<BR> sufficient.<BR><BR>5.12: I use the preprocessor macro "#define Nullptr(type) (type *)0"<BR> to help me build null pointers of the correct type.<BR><BR>A: This trick, though valid, does not buy much.<BR><BR>5.13: This is strange. NULL is guaranteed to be 0, but the null<BR> pointer is not?<BR><BR>A: A "null pointer" is a language concept whose particular internal<BR> value does not matter. A null pointer is requested in source<BR> code with the character "0". "NULL" is a preprocessor macro,<BR> which is always #defined as 0 (or ((void *)0)).<BR><BR>5.14: Why is there so much confusion surrounding null pointers?<BR><BR>A: The fact that null pointers are represented both in source code,<BR> and internally to most machines, as zero invites unwarranted<BR> assumptions. The use of a preprocessor macro (NULL) may seem to<BR> suggest that the value could change some day, or on some weird<BR> machine.<BR><BR>5.15: I'm confused. I just can't understand all this null pointer<BR> stuff.<BR><BR>A: A simple rule is, "Always use `0' or `NULL' for null pointers,<BR> and always cast them when they are used as arguments in function<BR> calls."<BR><BR>5.16: Given all the confusion surrounding null pointers, wouldn't it<BR> be easier simply to require them to be represented internally by<BR> zeroes?<BR><BR>A: Such a requirement would accomplish little.<BR><BR>5.17: Seriously, have any actual machines really used nonzero null<BR> pointers?<BR><BR>A: Machines manufactured by Prime, Honeywell-Bull, and CDC, as well<BR> as Symbolics Lisp Machines, have done so.<BR><BR>5.20: What does a run-time "null pointer assignment" error mean?<BR><BR>A: It means that you've written, via a null pointer, to an invalid<BR> location. (See also question 16.8.)<BR><BR><BR>Section 6. Arrays and Pointers<BR><BR>6.1: I had the definition char a[6] in one source file, and in<BR> another I declared extern char *a. Why didn't it work?<BR><BR>A: The declaration extern char *a simply does not match the actual<BR> definition. Use extern char a[].<BR><BR>6.2: But I heard that char a[] was identical to char *a.<BR><BR>A: Not at all. Arrays are not pointers. A reference like x[3]<BR> generates different code depending on whether x is an array or a<BR> pointer.<BR><BR>6.3: So what is meant by the "equivalence of pointers and arrays" in<BR> C?<BR><BR>A: An lvalue of type array-of-T which appears in an expression<BR> decays into a pointer to its first element; the type of the<BR> resultant pointer is pointer-to-T. So for an array a and<BR> pointer p, you can say "p = a;" and then p[3] and a[3] will<BR> access the same element.<BR><BR>6.4: Why are array and pointer declarations interchangeable as<BR> function formal parameters?<BR><BR>A: It's supposed to be a convenience.<BR><BR>6.7: How can an array be an lvalue, if you can't assign to it?<BR><BR>A: An array is not a "modifiable lvalue."<BR><BR>6.8: What is the real difference between arrays and pointers?<BR><BR>A: Arrays automatically allocate space which is fixed in size and<BR> location; pointers are dynamic.<BR><BR>6.9: Someone explained to me that arrays were really just constant<BR> pointers.<BR><BR>A: An array name is "constant" in that it cannot be assigned to,<BR> but an array is *not* a pointer.<BR><BR>6.11: I came across some "joke" code containing the "expression"<BR> 5["abcdef"] . How can this be legal C?<BR><BR>A: Yes, array subscripting is commutative in C. The array<BR> subscripting operation a[e] is defined as being identical to<BR> *((a)+(e)).<BR><BR>6.12: What's the difference between array and &array?<BR><BR>A: The type.<BR><BR>6.13: How do I declare a pointer to an array?<BR><BR>A: Usually, you don't want to. Consider using a pointer to one of<BR> the array's elements instead.<BR><BR>6.14: How can I set an array's size at run time?<BR><BR>A: It's straightforward to use malloc() and a pointer.<BR><BR>6.15: How can I declare local arrays of a size matching a passed-in<BR> array?<BR><BR>A: Until recently, you couldn't; array dimensions had to be compile-<BR> time constants. C9X will fix this.<BR><BR>6.16: How can I dynamically allocate a multidimensional array?<BR><BR>A: The traditional solution is to allocate an array of pointers,<BR> and then initialize each pointer to a dynamically-allocated<BR> "row." See the full list for code samples.<BR><BR>6.17: Can I simulate a non-0-based array with a pointer?<BR><BR>A: Not if the pointer points outside of the block of memory it is<BR> intended to access.<BR><BR>6.18: My compiler complained when I passed a two-dimensional array to<BR> a function expecting a pointer to a pointer.<BR><BR>A: The rule by which arrays decay into pointers is not applied<BR> recursively. An array of arrays (i.e. a two-dimensional array<BR> in C) decays into a pointer to an array, not a pointer to a<BR> pointer.<BR><BR>6.19: How do I write functions which accept two-dimensional arrays<BR> when the width is not known at compile time?<BR><BR>A: It's not always particularly easy.<BR><BR>6.20: How can I use statically- and dynamically-allocated<BR> multidimensional arrays interchangeably when passing them to<BR> functions?<BR><BR>A: There is no single perfect method, but see the full list for<BR> some ideas.<BR><BR>6.21: Why doesn't sizeof properly report the size of an array which is<BR> a parameter to a function?<BR><BR>A: The sizeof operator reports the size of the pointer parameter<BR> which the function actually receives.<BR><BR><BR>Section 7. Memory Allocation<BR><BR>7.1: Why doesn't the code "char *answer; gets(answer);" work?<BR><BR>A: The pointer variable answer has not been set to point to any<BR> valid storage. The simplest way to correct this fragment is to<BR> use a local array, instead of a pointer.<BR><BR>7.2: I can't get strcat() to work. I tried "char *s3 =<BR> strcat(s1, s2);" but I got strange results.<BR><BR>A: Again, the main problem here is that space for the concatenated<BR> result is not properly allocated.<BR><BR>7.3: But the man page for strcat() says that it takes two char *'s as<BR> arguments. How am I supposed to know to allocate things?<BR><BR>A: In general, when using pointers you *always* have to consider<BR> memory allocation, if only to make sure that the compiler is<BR> doing it for you.<BR><BR>7.3b: I just tried the code "char *p; strcpy(p, "abc");" and it<BR> worked. Why didn't it crash?<BR><BR>A: You got "lucky".<BR><BR>7.3c: How much memory does a pointer variable allocate?<BR><BR>A: Only enough memory to hold the pointer itself, not any memory<BR> for the pointer to point to.<BR><BR>7.5a: I have a function that is supposed to return a string, but when<BR> it returns to its caller, the returned string is garbage.<BR><BR>A: Make sure that the pointed-to memory is properly (i.e. not<BR> locally) allocated.<BR><BR>7.5b: So what's the right way to return a string?<BR><BR>A: Return a pointer to a statically-allocated buffer, a buffer<BR> passed in by the caller, or memory obtained with malloc().<BR><BR>7.6: Why am I getting "warning: assignment of pointer from integer<BR> lacks a cast" for calls to malloc()?<BR><BR>A: Have you #included <stdlib.h>?<BR><BR>7.7: Why does some code carefully cast the values returned by malloc<BR> to the pointer type being allocated?<BR><BR>A: Before ANSI/ISO C, these casts were required to silence certain<BR> warnings.<BR><BR>7.8: Why does so much code leave out the multiplication by<BR> sizeof(char) when allocating strings?<BR><BR>A: Because sizeof(char) is, by definition, exactly 1.<BR><BR>7.14: I've heard that some operating systems don't actually allocate<BR> malloc'ed memory until the program tries to use it. Is this<BR> legal?<BR><BR>A: It's hard to say.<BR><BR>7.16: I'm allocating a large array for some numeric work, but malloc()<BR> is acting strangely.<BR><BR>A: Make sure the number you're trying to pass to malloc() isn't<BR> bigger than a size_t can hold.<BR><BR>7.17: I've got 8 meg of memory in my PC. Why can I only seem to<BR> malloc 640K or so?<BR><BR>A: Under the segmented architecture of PC compatibles, it can be<BR> difficult to use more than 640K with any degree of transparency.<BR> See also question 19.23.<BR><BR>7.19: My program is crashing, apparently somewhere down inside malloc.<BR><BR>A: Make sure you aren't using more memory than you malloc'ed,<BR> especially for strings (which need strlen(str) + 1 bytes).<BR><BR>7.20: You can't use dynamically-allocated memory after you free it,<BR> can you?<BR><BR>A: No. Some early documentation implied otherwise, but the claim<BR> is no longer valid.<BR><BR>7.21: Why isn't a pointer null after calling free()?<BR><BR>A: C's pass-by-value semantics mean that called functions can never<BR> permanently change the values of their arguments.<BR><BR>7.22: When I call malloc() to allocate memory for a local pointer, do<BR> I have to explicitly free() it?<BR><BR>A: Yes.<BR><BR>7.23: When I free a dynamically-allocated structure containing<BR> pointers, do I also have to free each subsidiary pointer?<BR><BR>A: Yes.<BR><BR>7.24: Must I free allocated memory before the program exits?<BR><BR>A: You shouldn't have to.<BR><BR>7.25: Why doesn't my program's memory usage go down when I free<BR> memory?<BR><BR>A: Most implementations of malloc/free do not return freed memory<BR> to the operating system.<BR><BR>7.26: How does free() know how many bytes to free?<BR><BR>A: The malloc/free implementation remembers the size of each block<BR> as it is allocated.<BR><BR>7.27: So can I query the malloc package to find out how big an<BR> allocated block is?<BR><BR>A: Not portably.<BR><BR>7.30: Is it legal to pass a null pointer as the first argument to<BR> realloc()?<BR><BR>A: ANSI C sanctions this usage, although several earlier<BR> implementations do not support it.<BR><BR>7.31: What's the difference between calloc() and malloc()?<BR><BR>A: calloc() takes two arguments, and initializes the allocated<BR> memory to all-bits-0.<BR><BR>7.32: What is alloca() and why is its use discouraged?<BR><BR>A: alloca() allocates memory which is automatically freed when the<BR> function which called alloca() returns. alloca() cannot be<BR> written portably, is difficult to implement on machines without<BR> a stack, and fails under certain conditions if implemented<BR> simply.<BR><BR><BR>Section 8. Characters and Strings<BR><BR>8.1: Why doesn't "strcat(string, '!');" work?<BR><BR>A: strcat() concatenates *strings*, not characters.<BR><BR>8.2: Why won't the test if(string == "value") correctly compare<BR> string against the value?<BR><BR>A: It's comparing pointers. To compare two strings, use strcmp().<BR><BR>8.3: Why can't I assign strings to character arrays?<BR><BR>A: Strings are arrays, and you can't assign arrays directly. Use<BR> strcpy() instead.<BR><BR>8.6: How can I get the numeric (character set) value corresponding to<BR> a character?<BR><BR>A: In C, if you have the character, you have its value.<BR><BR>8.9: Why is sizeof('a') not 1?<BR><BR>A: Character constants in C are of type int.<BR><BR><BR>Section 9. Boolean Expressions and Variables<BR><BR>9.1: What is the right type to use for Boolean values in C?<BR><BR>A: There's no one right answer; see the full list for some<BR> discussion.<BR><BR>9.2: What if a built-in logical or relational operator "returns"<BR> something other than 1?<BR><BR>A: When a Boolean value is generated by a built-in operator, it is<BR> guaranteed to be 1 or 0. (This is *not* true for some library<BR> routines such as isalpha.)<BR><BR>9.3: Is if(p), where p is a pointer, valid?<BR><BR>A: Yes. See question 5.3.<BR><BR><BR>Section 10. C Preprocessor<BR><BR>10.2: I've got some cute preprocessor macros that let me write C code<BR> that looks more like Pascal. What do y'all think?<BR><BR>A: Bleah.<BR><BR>10.3: How can I write a generic macro to swap two values?<BR><BR>A: There is no good answer to this question. The best all-around<BR> solution is probably to forget about using a macro.<BR><BR>10.4: What's the best way to write a multi-statement macro?<BR><BR>A: #define Func() do {stmt1; stmt2; ... } while(0) /* (no trailing ;) */<BR><BR>10.6: What are .h files and what should I put in them?<BR><BR>A: Header files (also called ".h files") should generally contain<BR> common declarations and macro, structure, and typedef<BR> definitions, but not variable or function definitions.<BR><BR>10.7: Is it acceptable for one header file to #include another?<BR><BR>A: It's a question of style, and thus receives considerable debate.<BR><BR>10.8a: What's the difference between #include <> and #include "" ?<BR><BR>A: Roughly speaking, the <> syntax is for Standard headers and ""<BR> is for project headers.<BR><BR>10.8b: What are the complete rules for header file searching?<BR><BR>A: The exact behavior is implementation-defined; see the full list<BR> for some discussion.<BR><BR>10.9: I'm getting strange syntax errors on the very first declaration<BR> in a file, but it looks fine.<BR><BR>A: Perhaps there's a missing semicolon at the end of the last<BR> declaration in the last header file you're #including.<BR><BR>10.10b: I'm #including the header file for a function, but the linker<BR> keeps saying it's undefined.<BR><BR>A: See question 13.25.<BR><BR>10.11: Where can I get a copy of a missing header file?<BR><BR>A: Contact your vendor, or see question 18.16 or the full list.<BR><BR>10.12: How can I construct preprocessor #if expressions which compare<BR> strings?<BR><BR>A: You can't do it directly; try #defining several manifest<BR> constants and implementing conditionals on those.<BR><BR>10.13: Does the sizeof operator work in preprocessor #if directives?<BR><BR>A: No.<BR><BR>10.14: Can I use an #ifdef in a #define line, to define something two<BR> different ways?<BR><BR>A: No.<BR><BR>10.15: Is there anything like an #ifdef for typedefs?<BR><BR>A: Unfortunately, no.<BR><BR>10.16: How can I use a preprocessor #if expression to detect<BR> endianness?<BR><BR>A: You probably can't.<BR><BR>10.18: How can I preprocess some code to remove selected conditional<BR> compilations, without preprocessing everything?<BR><BR>A: Look for a program called unifdef, rmifdef, or scpp.<BR><BR>10.19: How can I list all of the predefined identifiers?<BR><BR>A: If the compiler documentation is unhelpful, try extracting<BR> printable strings from the compiler or preprocessor executable.<BR><BR>10.20: I have some old code that tries to construct identifiers with a<BR> macro like "#define Paste(a, b) a/**/b", but it doesn't work any<BR> more.<BR><BR>A: Try the ANSI token-pasting operator ##.<BR><BR>10.22: What does the message "warning: macro replacement within a<BR> string literal" mean?<BR><BR>A: See question 11.18.<BR><BR>10.23-4: I'm having trouble using macro arguments inside string<BR> literals, using the `#' operator.<BR><BR>A: See questions 11.17 and 11.18.<BR><BR>10.25: I've got this tricky preprocessing I want to do and I can't<BR> figure out a way to do it.<BR><BR>A: Consider writing your own little special-purpose preprocessing<BR> tool, instead.<BR><BR>10.26: How can I write a macro which takes a variable number of<BR> arguments?<BR><BR>A: Here is one popular trick. Note that the parentheses around<BR> printf's argument list are in the macro call, not the<BR> definition.<BR><BR> #define DEBUG(args) (printf("DEBUG: "), printf args)<BR><BR> if(n != 0) DEBUG(("n is %d\n", n));<BR><BR><BR>Section 11. ANSI/ISO Standard C<BR><BR>11.1: What is the "ANSI C Standard?"<BR><BR>A: In 1983, the American National Standards Institute (ANSI)<BR> commissioned a committee to standardize the C language. Their<BR> work was ratified as ANS X3.159-1989, and has since been adopted<BR> as ISO/IEC 9899:1990, and later amended.<BR><BR>11.2: How can I get a copy of the Standard?<BR><BR>A: Copies are available from ANSI in New York, or from Global<BR> Engineering Documents in Englewood, CO, or from any national<BR> standards body, or from ISO in Geneva, or republished within one<BR> or more books. See the unabridged list for details.<BR><BR>11.2b: Where can I get information about updates to the Standard?<BR><BR>A: See the full list for pointers.<BR><BR>11.3: My ANSI compiler is complaining about prototype mismatches for<BR> parameters declared float.<BR><BR>A: You have mixed the new-style prototype declaration<BR> "extern int func(float);" with the old-style definition<BR> "int func(x) float x;". "Narrow" types are treated differently<BR> according to which syntax is used. This problem can be fixed by<BR> avoiding narrow types, or by using either new-style (prototype)<BR> or old-style syntax consistently.<BR><BR>11.4: Can you mix old-style and new-style function syntax?<BR><BR>A: Doing so is currently legal, for most argument types<BR> (see question 11.3).<BR><BR>11.5: Why does the declaration "extern int f(struct x *p);" give me a<BR> warning message?<BR><BR>A: A structure declared (or even mentioned) for the first time<BR> within a prototype cannot be compatible with other structures<BR> declared in the same source file.<BR><BR>11.8: Why can't I use const values in initializers and array<BR> dimensions?<BR><BR>A: The value of a const-qualified object is *not* a constant<BR> expression in the full sense of the term.<BR><BR>11.9: What's the difference between "const char *p" and<BR> "char * const p"?<BR><BR>A: The former declares a pointer to a constant character; the<BR> latter declares a constant pointer to a character.<BR><BR>11.10: Why can't I pass a char ** to a function which expects a<BR> const char **?<BR><BR>A: The rule which permits slight mismatches in qualified pointer<BR> assignments is not applied recursively.<BR><BR>11.12a: What's the correct declaration of main()?<BR><BR>A: int main(int argc, char *argv[]) .<BR><BR>11.12b: Can I declare main() as void, to shut off these annoying "main<BR> returns no value" messages?<BR><BR>A: No.<BR><BR>11.13: But what about main's third argument, envp?<BR><BR>A: It's a non-standard (though common) extension.<BR><BR>11.14: I believe that declaring void main() can't fail, since I'm<BR> calling exit() instead of returning.<BR><BR>A: It doesn't matter whether main() returns or not, the problem is<BR> that its caller may not even be able to *call* it correctly.<BR><BR>11.15: The book I've been using always uses void main().<BR><BR>A: It's wrong.<BR><BR>11.16: Is exit(status) truly equivalent to returning the same status<BR> from main()?<BR><BR>A: Yes and no. (See the full list for details.)<BR><BR>11.17: How do I get the ANSI "stringizing" preprocessing operator `#'<BR> to stringize the macro's value instead of its name?<BR><BR>A: You can use a two-step #definition to force a macro to be<BR> expanded as well as stringized.<BR><BR>11.18: What does the message "warning: macro replacement within a<BR> string literal" mean?<BR><BR>A: Some pre-ANSI compilers/preprocessors expanded macro parameters<BR> even inside string literals and character constants.<BR><BR>11.19: I'm getting strange syntax errors inside lines I've #ifdeffed<BR> out.<BR><BR>A: Under ANSI C, #ifdeffed-out text must still consist of "valid<BR> preprocessing tokens." This means that there must be no<BR> newlines inside quotes, and no unterminated comments or quotes<BR> (i.e. no single apostrophes).<BR><BR>11.20: What are #pragmas ?<BR><BR>A: The #pragma directive provides a single, well-defined "escape<BR> hatch" which can be used for extensions.<BR><BR>11.21: What does "#pragma once" mean?<BR><BR>A: It is an extension implemented by some preprocessors to help<BR> make header files idempotent.<BR><BR>11.22: Is char a[3] = "abc"; legal?<BR><BR>A: Yes, in ANSI C.<BR><BR>11.24: Why can't I perform arithmetic on a void * pointer?<BR><BR>A: The compiler doesn't know the size of the pointed-to objects.<BR><BR>11.25: What's the difference between memcpy() and memmove()?<BR><BR>A: memmove() offers guaranteed behavior if the source and<BR> destination arguments overlap.<BR><BR>11.26: What should malloc(0) do?<BR><BR>A: The behavior is implementation-defined.<BR><BR>11.27: Why does the ANSI Standard not guarantee more than six case-<BR> insensitive characters of external identifier significance?<BR><BR>A: The problem is older linkers which cannot be forced (by mere<BR> words in a Standard) to upgrade.<BR><BR>11.29: My compiler is rejecting the simplest possible test programs,<BR> with all kinds of syntax errors.<BR><BR>A: Perhaps it is a pre-ANSI compiler.<BR><BR>11.30: Why are some ANSI/ISO Standard library functions showing up as<BR> undefined, even though I've got an ANSI compiler?<BR><BR>A: Perhaps you don't have ANSI-compatible headers and libraries.<BR><BR>11.31: Does anyone have a tool for converting old-style C programs to<BR> ANSI C, or for automatically generating prototypes?<BR><BR>A: See the full list for details.<BR><BR>11.32: Why won't frobozz-cc, which claims to be ANSI compliant, accept<BR> this code?<BR><BR>A: Are you sure that the code being rejected doesn't rely on some<BR> non-Standard extension?<BR><BR>11.33: What's the difference between implementation-defined,<BR> unspecified, and undefined behavior?<BR><BR>A: If you're writing portable code, ignore the distinctions.<BR> Otherwise, see the full list.<BR><BR>11.34: I'm appalled that the ANSI Standard leaves so many issues<BR> undefined.<BR><BR>A: In most of these cases, the Standard is simply codifying<BR> existing practice.<BR><BR>11.35: I just tried some allegedly-undefined code on an ANSI-conforming<BR> compiler, and got the results I expected.<BR><BR>A: A compiler may do anything it likes when faced with undefined<BR> behavior, including doing what you expect.<BR><BR><BR>Section 12. Stdio<BR><BR>12.1: What's wrong with the code "char c; while((c = getchar()) !=<BR> EOF) ..."?<BR><BR>A: The variable to hold getchar's return value must be an int.<BR><BR>12.2: Why won't the code "while(!feof(infp)) {<BR> fgets(buf, MAXLINE, infp); fputs(buf, outfp); }" work?<BR><BR>A: EOF is only indicated *after* an input routine fails.<BR><BR>12.4: My program's prompts and intermediate output don't always show<BR> up on the screen.<BR><BR>A: It's best to use an explicit fflush(stdout) whenever output<BR> should definitely be visible.<BR><BR>12.5: How can I read one character at a time, without waiting for the<BR> RETURN key?<BR><BR>A: See question 19.1.<BR><BR>12.6: How can I print a '%' character with printf?<BR><BR>A: "%%".<BR><BR>12.9: How can printf() use %f for type double, if scanf() requires<BR> %lf?<BR><BR>A: C's "default argument promotions" mean that values of type float<BR> are promoted to double.<BR><BR>12.9b: What printf format should I use for a typedef when I don't know<BR> the underlying type?<BR><BR>A: Use a cast to convert the value to a known type, then use the<BR> printf format matching that type.<BR><BR>12.10: How can I implement a variable field width with printf?<BR><BR>A: Use printf("%*d", width, x).<BR><BR>12.11: How can I print numbers with commas separating the thousands?<BR><BR>A: There is no standard routine (but see <locale.h>).<BR><BR>12.12: Why doesn't the call scanf("%d", i) work?<BR><BR>A: The arguments you pass to scanf() must always be pointers.<BR><BR>12.13: Why doesn't the code "double d; scanf("%f", &d);" work?<BR><BR>A: Unlike printf(), scanf() uses %lf for double, and %f for float.<BR><BR>12.15: How can I specify a variable width in a scanf() format string?<BR><BR>A: You can't.<BR><BR>12.17: When I read numbers from the keyboard with scanf "%d\n", it<BR> seems to hang until I type one extra line of input.<BR><BR>A: Try using "%d" instead of "%d\n".<BR><BR>12.18: I'm reading a number with scanf %d and then a string with<BR> gets(), but the compiler seems to be skipping the call to<BR> gets()!<BR><BR>A: scanf() and gets() do not work well together.<BR><BR>12.19: I'm re-prompting the user if scanf() fails, but sometimes it<BR> seems to go into an infinite loop.<BR><BR>A: scanf() tends to "jam" on bad input since it does not discard<BR> it.<BR><BR>12.20: Why does everyone say not to use scanf()? What should I use<BR> instead?<BR><BR>A: scanf() has a number of problems. Usually, it's easier to read<BR> entire lines and then interpret them.<BR><BR>12.21: How can I tell how much destination buffer space I'll need for<BR> an arbitrary sprintf call? How can I avoid overflowing the<BR> destination buffer with sprintf()?<BR><BR>A: Use the new snprintf() function, if you can.<BR><BR>12.23: Why does everyone say not to use gets()?<BR><BR>A: It cannot be prevented from overflowing the input buffer.<BR><BR>12.24: Why does errno contain ENOTTY after a call to printf()?<BR><BR>A: Don't worry about it. It is only meaningful for a program to<BR> inspect the contents of errno after an error has been reported.<BR><BR>12.25: What's the difference between fgetpos/fsetpos and ftell/fseek?<BR><BR>A: fgetpos() and fsetpos() use a special typedef which may allow<BR> them to work with larger files than ftell() and fseek().<BR><BR>12.26: Will fflush(stdin) flush unread characters from the standard<BR> input stream?<BR><BR>A: No.<BR><BR>12.30: I'm trying to update a file in place, by using fopen mode "r+",<BR> but it's not working.<BR><BR>A: Be sure to call fseek between reading and writing.<BR><BR>12.33: How can I redirect stdin or stdout from within a program?<BR><BR>A: Use freopen().<BR><BR>12.34: Once I've used freopen(), how can I get the original stream<BR> back?<BR><BR>A: There isn't a good way. Try avoiding freopen.<BR><BR>12.36b: How can I arrange to have output go two places at once?<BR><BR>A: You could write your own printf variant which printed everything<BR> twice. See question 15.5.<BR><BR>12.38: How can I read a binary data file properly?<BR><BR>A: Be sure to specify "rb" mode when calling fopen().<BR><BR><BR>Section 13. Library Functions<BR><BR>13.1: How can I convert numbers to strings?<BR><BR>A: Just use sprintf().<BR><BR>13.2: Why does strncpy() not always write a '\0'?<BR><BR>A: For mildly-interesting historical reasons.<BR><BR>13.5: Why do some versions of toupper() act strangely if given an<BR> upper-case letter?<BR><BR>A: Older versions of toupper() and tolower() did not always work as<BR> expected in this regard.<BR><BR>13.6: How can I split up a string into whitespace-separated fields?<BR><BR>A: Try strtok().<BR><BR>13.7: I need some code to do regular expression and wildcard matching.<BR><BR>A: regexp libraries abound; see the full list for details.<BR><BR>13.8: I'm trying to sort an array of strings with qsort(), using<BR> strcmp() as the comparison function, but it's not working.<BR><BR>A: You'll have to write a "helper" comparison function which takes<BR> two generic pointer arguments, converts them to char **, and<BR> dereferences them, yielding char *'s which can be usefully<BR> compared.<BR><BR>13.9: Now I'm trying to sort an array of structures, but the compiler<BR> is complaining that the function is of the wrong type for<BR> qsort().<BR><BR>A: The comparison function must be declared as accepting "generic<BR> pointers" (const void *) which it then converts to structure<BR> pointers.<BR><BR>13.10: How can I sort a linked list?<BR><BR>A: Algorithms like insertion sort and merge sort work well, or you<BR> can keep the list in order as you build it.<BR><BR>13.11: How can I sort more data than will fit in memory?<BR><BR>A: You want an "external sort"; see the full list for details.<BR><BR>13.12: How can I get the time of day in a C program?<BR><BR>A: Just use the time(), ctime(), localtime() and/or strftime()<BR> functions.<BR><BR>13.13: How can I convert a struct tm or a string into a time_t?<BR><BR>A: The ANSI mktime() function converts a struct tm to a time_t. No<BR> standard routine exists to parse strings.<BR><BR>13.14: How can I perform calendar manipulations?<BR><BR>A: The ANSI/ISO Standard C mktime() and difftime() functions<BR> provide some support for both problems.<BR><BR>13.14b: Does C have any Year 2000 problems?<BR><BR>A: No, although poorly-written C programs do. Make sure you know<BR> that tm_year holds the value of the year minus 1900.<BR><BR>13.15: I need a random number generator.<BR><BR>A: The Standard C library has one: rand().<BR><BR>13.16: How can I get random integers in a certain range?<BR><BR>A: One method is something like<BR><BR> (int)((double)rand() / ((double)RAND_MAX + 1) * N)<BR><BR>13.17: Each time I run my program, I get the same sequence of numbers<BR> back from rand().<BR><BR>A: You can call srand() to seed the pseudo-random number generator<BR> with a truly random initial value.<BR><BR>13.18: I need a random true/false value, so I'm just taking rand() % 2,<BR> but it's alternating 0, 1, 0, 1, 0...<BR><BR>A: Try using the higher-order bits: see question 13.16.<BR><BR>13.20: How can I generate random numbers with a normal or Gaussian<BR> distribution?<BR><BR>A: See the longer versions of this list for ideas.<BR><BR>13.24: I'm trying to port this old program. Why do I get "undefined<BR> external" errors for some library functions?<BR><BR>A: Some semistandard functions have been renamed or replaced over<BR> the years; see the full list for details.<BR><BR>13.25: I get errors due to library functions being undefined even<BR> though I #include the right header files.<BR><BR>A: You may have to explicitly ask for the correct libraries to be<BR> searched.<BR><BR>13.26: I'm still getting errors due to library functions being<BR> undefined, even though I'm requesting the right libraries.<BR><BR>A: Library search order is significant; usually, you must search<BR> the libraries last.<BR><BR>13.28: What does it mean when the linker says that _end is undefined?<BR><BR>A: You generally get that message only when other symbols are<BR> undefined, too.<BR><BR><BR>Section 14. Floating Point<BR><BR>14.1: When I set a float variable to 3.1, why is printf printing it as<BR> 3.0999999?<BR><BR>A: Most computers use base 2 for floating-point numbers, and many<BR> fractions (including 0.1 decimal) are not exactly representable<BR> in base 2.<BR><BR>14.2: Why is sqrt(144.) giving me crazy numbers?<BR><BR>A: Make sure that you have #included <math.h>, and correctly<BR> declared other functions returning double.<BR><BR>14.3: I keep getting "undefined: sin" compilation errors.<BR><BR>A: Make sure you're actually linking with the math library.<BR><BR>14.4: My floating-point calculations are acting strangely and giving<BR> me different answers on different machines.<BR><BR>A: First, see question 14.2 above. If the problem isn't that<BR> simple, see the full list for a brief explanation, or any good<BR> programming book for a better one.<BR><BR>14.5: What's a good way to check for "close enough" floating-point<BR> equality?<BR><BR>A: The best way is to use an accuracy threshold which is relative<BR> to the magnitude of the numbers being compared.<BR><BR>14.6: How do I round numbers?<BR><BR>A: For positive numbers, try (int)(x + 0.5) .<BR><BR>14.7: Where is C's exponentiation operator?<BR><BR>A: Try using the pow() function.<BR><BR>14.8: The predefined constant M_PI seems to be missing from <math.h>.<BR><BR>A: That constant is not standard.<BR><BR>14.9: How do I test for IEEE NaN and other special values?<BR><BR>A: There is not yet a portable way, but see the full list for<BR> ideas.<BR><BR>14.11: What's a good way to implement complex numbers in C?<BR><BR>A: It is straightforward to define a simple structure and some<BR> arithmetic functions to manipulate them.<BR><BR>14.12: I'm looking for some mathematical library code.<BR><BR>A: See Ajay Shah's index of free numerical software at<BR> ftp://ftp.math.psu.edu/pub/FAQ/numcomp-free-c .<BR><BR>14.13: I'm having trouble with a Turbo C program which crashes and says<BR> something like "floating point formats not linked."<BR><BR>A: You may have to insert a dummy call to a floating-point library<BR> function to force loading of floating-point support.<BR><BR><BR>Section 15. Variable-Length Argument Lists<BR><BR>15.1: I heard that you have to #include <stdio.h> before calling<BR> printf(). Why?<BR><BR>A: So that a proper prototype for printf() will be in scope.<BR><BR>15.2: How can %f be used for both float and double arguments in<BR> printf()?<BR><BR>A: In variable-length argument lists, types char and short int are<BR> promoted to int, and float is promoted to double.<BR><BR>15.3: Why don't function prototypes guard against mismatches in<BR> printf's arguments?<BR><BR>A: Function prototypes do not provide any information about the<BR> number and types of variable arguments.<BR><BR>15.4: How can I write a function that takes a variable number of<BR> arguments?<BR><BR>A: Use the <stdarg.h> header.<BR><BR>15.5: How can I write a function that takes a format string and a<BR> variable number of arguments, like printf(), and passes them to<BR> printf() to do most of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -