Chapter 1. An Overview of ANSI C

This chapter briefly discusses the scope of the new standard and lists some programming practices to avoid and some to use.

ANSI C

The ANSI standard on the C programming language is designed to promote the portability of C programs among a variety of data-processing systems. To accomplish this, the standard covers three major areas: the environment in which the program compiles and executes, the semantics and syntax of the language, and the content and semantics of a set of library routines and header files.

Strictly Conforming Programs

Strictly conforming programs adhere to the following guidelines:

  • They use only those features of the language defined in the standard.

  • They do not produce output dependent on any ill-defined behavior. Ill-defined behavior includes implementation-defined, undefined, and unspecified behavior which refers to areas that the standard does not specify.

  • They do not exceed any minimum limit.

This ANSI C environment is designed to be a conforming hosted implementation, which will accept any strictly conforming program. Extensions are allowed only if the behavior of strictly conforming programs is not altered.

Name Spaces

Besides knowing which features of the language and library you can rely on when writing portable programs, you must be able to avoid naming conflicts with support routines used for the implementation of the library. To avoid such naming conflicts, ANSI divides the space of available names into a set reserved for the user and a set reserved for the implementation. Any name is in the user's name space if it meets these three requirements (this rule is given for simplicity; the space of names reserved for the user is actually somewhat larger than this):

  • It does not begin with an underscore

  • It is not a keyword in the language

  • It is not reserved for the ANSI library

Strictly conforming programs may not define any names unless they are in the user's namespace. New keywords as well as those names reserved for the ANSI library are discussed in “Standard Headers” in Chapter 2.

Compiling ANSI Programs

To provide the portable clean environment dictated by ANSI while retaining the many extensions available to Silicon Graphics users, two modes of compilation are provided for ANSI programs. Each of these switches to the cc command invokes the ANSI compiler:

-ansi

Enforces a pure ANSI environment, eliminating Silicon Graphics extensions. The ANSI symbol indicating a pure environment (__STDC__) is defined to be 1 for the preprocessor. Use this mode when compiling strictly conforming programs, because it guarantees purity of the ANSI namespace.

-xansi

Adds Silicon Graphics extensions to the environment. This mode is the default. The ANSI preprocessor symbol (__STDC__) is defined to be 1. The symbol to include extensions from standard headers (__EXTENSIONS__) is also defined, as is the symbol to inline certain library routines that are directly supported by the hardware (__INLINE_INTRINSICS.) Note that when these library routines are made to be intrinsic, they may no longer be strictly ANSI conforming (for example, errno may not be set correctly).

Guidelines for Using ANSI C

The following are some key facts to keep in mind when you use ANSI C:

  • Use only -lc and/or -lm to specify the C and/or math libraries. These switches ensure the incorporation of the ANSI version of these libraries.

  • Use the switch -fullwarn to receive additional diagnostic warnings that are suppressed by default. Silicon Graphics recommends using this option with the -woff option to remove selected warnings during software development.

  • Use the switch -wlint (-o32 mode only) to get lint-like warnings about the compiled source. This option provides lint-like warnings for ANSI and -cckr modes and can be used together with the other cc options and switches.

  • Remember that the default compilation mode is shared and the libraries are shared.

Compiling Traditional C Programs

To compile code using traditional C (that is, non-ANSI), use the switch -cckr. The dialect of C invoked by [-cckr] is referred to interchangeably as -cckr, "the previous version of Silicon Graphics C," and "traditional C" in the remainder of this document.

You can find complete information concerning ANSI and non-ANSI compilation modes in the cc(1) online reference page.

Helpful Programming Hints

Although the ANSI Standard has added only a few new features to the C language, it has tightened the semantics of many areas. In some cases, constructs were removed that were ambiguous, no longer used, or obvious hacks. The next two sections give two lists of programming practices. The first section recommends practices that you can use to ease your transition to this new environment. The second section lists common C coding practices that cause problems when you use ANSI C.

Recommended Practices

Follow these recommendations as you code:

  • Always use the appropriate header file when declaring standard external functions. Avoid embedding the declaration in your code. This avoids inconsistent declarations for the same function.

  • Always use function prototypes, and write your function prologues in function prototype form.

  • Use the offsetof() macro to derive structure member offsets. The offsetof() macro is in <stddef.h>.

  • Always use casts when converting.

  • Be strict with your use of qualified objects, such as with volatile and const. Assign the addresses of these objects only to pointers that are so qualified.

  • Return a value from all return points of all non-void functions.

  • Use only structure designators of the appropriate type as the structure designator in . and -> expressions (that is, ensure that the right side is a member of the structure on the left side).

  • Always specify the types of integer bitfields as signed or unsigned.

Practices to Avoid

Avoid the following as you code:

  • Never mix prototyped and nonprototyped declarations of the same function.

  • Never call a function before it has been declared. This may lead to an incompatible implicit declaration for the function. In particular, this is unlikely to work for prototyped functions that take a variable number of arguments.

  • Never rely on the order in which arguments are evaluated. For example, what is the result of the code fragment foo(a++, a, ...)?

  • Avoid using expressions with side effects as arguments to a function.

  • Avoid two side effects to the same data location between two successive sequence points (for example, x=++x;).

  • Avoid declaring functions in a local context, especially if they have prototypes.

  • Never access parameters that are not specified in the argument list unless using the stdarg facilities. Use the stdarg facilities only on a function with an unbounded argument list (that is, an argument list terminated with ...).

  • Never cast a pointer type to anything other than another pointer type or an integral type of the same size (unsigned long), and vice versa. Use a union type to access the bit-pattern of a pointer as a nonintegral and nonpointer type (that is, as an array of chars).

  • Do not hack preprocessor tokens (for example, FOO/**/BAR).

  • Never modify a string literal.

  • Do not rely on search rules to locate include files that you specify with quotation marks.