Thursday, July 1, 2010

ANSI C Questions

1. What is the "ANSI C Standard?"

A: In 1983, the American National Standards Institute commissioned a committee, X3J11, to standardize the C language. After a long, arduous process, including several widespread public reviews, the committee's work was finally ratified as an American National Standard, X3.159-1989, on December 14, 1989, and published in the spring of 1990. For the most part, ANSI C standardizes existing practice, with a few additions from C++ (most notably function prototypes) and support for multinational character sets (including the much-lambasted trigraph sequences). The ANSI C standard also formalizes the C run-time library support routines.

The published Standard includes a "Rationale," which explains many of its decisions, and discusses a number of subtle points, including several of those covered here. (The Rationale is "not part of ANSI Standard X3.159-1989, but is included for information only.")

The Standard has been adopted as an international standard, ISO/IEC 9899:1990, although the Rationale is currently not included.

2. How can I get a copy of the Standard?

A: Copies are available from
American National Standards Institute
1430 Broadway
New York, NY 10018 USA
(+1) 212 642 4900
or
Global Engineering Documents
2805 McGaw Avenue
Irvine, CA 92714 USA
(+1) 714 261 1455
(800) 854 7179 (U.S. & Canada)

The cost from ANSI is $50.00, plus $6.00 shipping. Quantity discounts are available. (Note that ANSI derives revenues to support its operations from the sale of printed standards, so
electronic copies are _not_ available.)
Silicon Press, ISBN 0-929306-07-4, has printed the Rationale, by itself.

3. Does anyone have a tool for converting old-style C programs to ANSI C, or for automatically generating prototypes?

A: Two programs, protoize and unprotoize, convert back and forth between prototyped and "old style" function definitions and declarations. (These programs do _not_ handle full-blown
translation between "Classic" C and ANSI C.) These programs exist as patches to the FSF GNU C compiler, gcc. Look for the file protoize-1.39.0 in pub/gnu at prep.ai.mit.edu (18.71.0.38), or at several other FSF archive sites.

Several prototype generators exist, many as modifications to lint. (See also question 94.)

4. What's the difference between "char const *p" and "char * const p"?

A: "char const *p" is a pointer to a constant character (you can't change the character); "char * const p" is a constant pointer to a (variable) character (i.e. you can't change the pointer). (Read these "inside out" to understand them. See question 66.)

5. My ANSI compiler complains about a mismatch when it sees
extern int func(float);
int func(x)
float x;
{...

A: You have mixed the new-style prototype declaration "extern int func(float);" with the old-style definition "int func(x) float x;". Old C (and ANSI C, in the absence of prototypes) silently promotes floats to doubles when passing them as arguments, and arranges that doubles being passed are coerced back to floats if the formal parameters are declared that way.

The problem can be fixed either by using new-style syntax consistently in the definition:
int func(float x) { ... }

or by changing the new-style prototype declaration to match the old-style definition:
extern int func(double);

(In this case, it would be clearest to change the old-style definition to use double as well, as long as the address of that parameter is not taken.)

6. I'm getting strange syntax errors inside code which I've #ifdeffed out.

A: Under ANSI C, the text inside a "turned off" #if, #ifdef, or #ifndef must still consist of "valid preprocessing tokens." This means that there must be no unterminated comments or quotes (note particularly that an apostrophe within a contracted word could look like the beginning of a character constant), and no newlines inside quotes. Therefore, natural-language comments and pseudocode should always be written between the "official" comment delimiters /* and
*/. (But see also question 96.)


7. Can I declare main as void, to shut off these annoying "main returns no value" messages? (I'm calling exit(), so main doesn't return.)

A: No. main must be declared as returning an int, and as taking either zero or two arguments (of the appropriate type). If you're calling exit() but still getting warnings, you'll have to insert a redundant return statement (or use a "notreached" directive, if available).


8. Why does the ANSI Standard not guarantee more than six monocase characters of external identifier significance?

A: The problem is older linkers, which are neither under the control of the ANSI standard nor the C compiler developers on the systems, which have them. The limitation is only those identifiers be
_significant_ in the first six characters, not that they be restricted to six characters in length. This limitation is annoying, but certainly not unbearable, and is marked in the
Standard as "obsolescent," i.e. a future revision will likely relax it.

This concession to current, restrictive linkers really had to be made, no matter how vehemently some people oppose it. (The Rationale notes that its retention was "most painful.") If you disagree, or have thought of a trick by which a compiler burdened with a restrictive linker could present the C programmer with the appearance of more significance in external identifiers, read the excellently worded section 3.1.2 in the X3.159 Rationale (see question 28), which discusses several such schemes and explains why they could not be mandated.


9. What was noalias and what ever happened to it?

A: noalias was another type qualifier, in the same syntactic class as const and volatile, which was intended to assert that the object pointed to was not also pointed to ("aliased") by other pointers.
It was phenomenally difficult to define precisely and explain coherently, and sparked widespread, acrimonious debate. Because of the criticism and the difficulty of defining noalias well, the
Committee wisely declined to adopt it, in spite of its superficial attractions.


10. What are #pragmas and what are they good for?

A: The #pragma directive provides a single, well defined “escape hatch” which can be used for all sorts of implementation-specific controls and extensions: source listing control, structure packing, warning suppression (like the old lint/* NOTREACHED*/ comments), etc.

1 comment:

  1. Aloha,

    Zoooooooom! That’s how speedy and easy this read was! Looking forward to more of such powerful content on ANSI C Questions !

    In a programming languge, we declare variables as follows:
    var name1,name2,.... : integer;
    othername1,othername2,... : real;
    otherothername1,... : boolean;
    other4name1,... : char;

    (a) Write a real life example of a variable declaration in this language.
    (b) Construct the syntactic diagram (this is about circles,squares and arrows
    and pretty frustrating, arrgh!)
    (c) Define the variables in Backus-Naur form.
    (d) Write the associated LEX program in C.
    (e) Define the tokens, lexemes and patterns existing in this process.
    (e) Define a formal expression regarding variable declaration in this language
    and construct the relevant finite automaton.

    Super likes !!! for this amazing post. I thinks everyone should bookmark this.

    Thanks,
    Irene Hynes

    ReplyDelete