Advanced Debugging Techniques

Chapter 14 - Advanced Programming Topics

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

Type Compatibility
You have learned that C is not a strongly typed language. C++ is only slightly more strongly typed (for example, enumerated types). You have also learned how C can perform automatic type conversions and explicit type conversions using the cast operator. The following section highlights the sometimes confusing way the compiler interprets compatible types.
ANSI C Definition for Type Compatibility
The ANSI C committee is chiefly responsible for the discussion of and solution to compatible types. Many of the committee’s recommendations added features to C that made the language more readily maintained, such as function prototyping. The committee tried to define a set of rules or coded syntax that nailed down the language’s automatic behind-the-scenes behavior.
The ANSI C committee decided that for two types to be compatible, they either must be the same type or must be pointers, functions, or arrays with certain properties (as described in the following sections).
What Is an Identical Type?
The term “composite type” is associated with the subject of compatibility. The composite type is the common type that is produced by two compatible types. Any two types that are the same are compatible, and their composite type is the same type.
Two arithmetic types are identical if they are the same type. Abbreviated declarations for the same type are also identical. In the following example, both shivalue1 and shivalue2 are identical types:
short shivalue1;
short int shivalue2;
Similarly, the type int is the same as signed int in this next example:
int sivalue1;
signed int sivalue2;
However, the types int, short, and unsigned are all different. When dealing with character data, the types char, signed char, and unsigned char are always different.
The ANSI C committee stated that any type preceded by an access modifier generates incompatible types. For example, the next two declarations are not compatible types:
int ivalue1;
const int ivalue2;
In this next set of declarations, see if you can guess which types are compatible:
char *pc1, * pc2;
struct {int ix, iy;} stanonymous_coord1, stanonymous_coord2;
struct stxy {int ix, iy;} stanycoords;
typedef struct stxy STXY;
STXY stmorecoords;
Both pc1 and pc2 are compatible character pointers since the additional space between the * symbol and pc2 in the declaration is superfluous.
You are probably not surprised that the compiler sees stanonymous_coord1 and stanonymous_coord2 as the same type. However, the compiler does not see stanycoords as being the identical type to the previous pair of variables. Even though all three variables seem to have the same two integer fields, stanonymous_coord1 and stanonymous_coord2 are of an anonymous structure type, while stanycoords is of tag type stxy.
Because of the typedef declaration, the compiler does see struct stxy as being the identical type to STXY. For this reason, stanycoords is identical to stmorecoords.
It is important to remember that the compiler sees typedef declarations as being synonymous for types, not totally new types. The following code segment defines a new type called MYFLOAT that is the same type as float:
typedef float MYFLOAT;
Enumerated Types
The ANSI C committee initially stated that each enumerated type be compatible with the implementation-specific integral type; this is not the case with C++. In C++, enumeration types are not compatible with integral types. In both C and C++, no two enumerated type definitions in the same source file are compatible. This rule is analogous to the tagged and untagged (anonymous) structures. This explains why ebflag1 and ebflag2 are compatible types, while eflag1 is not a compatible type:
enum boolean {0,1} ebflag1;
enum {0,1} eflag1;
enum boolean ebflag2;
Array Types
If two arrays have compatible array elements, the arrays are considered compatible. If only one array specifies a size, or neither does, the types are still compatible. However, if both arrays specify a size, both sizes must be identical for the arrays to be compatible. See if you can find all of the compatible arrays in the following declarations:
int imax20[20];
const int cimax20[20];
int imax10[10];
int iundefined[];
The undimensioned integer array iundefined is compatible with both imax20 and imax10. However, this last pair is incompatible because they use different array bounds. The arrays imax20 (element type int) and cimax20 (element type const int) are incompatible because their elements are not compatible. If either array specifies an array bound, the composite type of the compatible arrays has that size also. Using the code segment above, the composite type of iundefined and imax20 is int[20].
Function Types
There are three conditions that must be met in order for two prototyped functions to be considered compatible. The two functions must have the same return types and number of parameters, and the corresponding parameters must be compatible types. However, parameter names do not have to agree.
Structure and Union Types
Each new structure or union type introduces a new type that is not the same as, nor compatible with, any other type in the same source file. For this reason, the variables stanonymous1, stanonymous2, and stfloat1 in the following code segment are all different.
However, a reference to a type specifier that is a structure, union, or enumerated type is the same type. You use the tag field to associate the reference with the type declaration. For this reason, the tag field can be thought of as the name of the type. This rule explains why stfloat1 and stfloat2 are compatible types:
struct {float fvalue1, fvalue2;} stanonymous1;
struct {float fvalue1, fvalue2;} stanonymous2;
struct sttwofloats {float fvalue1, fvalue2} stfloat1;
struct sttwofloats stfloat2;
Pointer Types
Two pointer types are considered compatible if they both point to compatible types. The composite type of the two compatible pointers is the same as the pointed-to composite type.
Multiple Source File Compatibility
The compiler views each declaration of a structure, union, or enumerated type as being a new non-compatible type. This might raise the question, “What happens when you want to reference these types across files within the same program?”
Multiple structure, union, and enumerated declarations are compatible across source files if they declare the same members, in the same order, with compatible member types. However, with enumerated types, the enumeration constants do not have to be declared in the same order, although each constant must have the same enumeration value.

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net