Special Keywords in Declarations (Microsoft Specific)

The following special keywords can also be used in declarations. Since these keywords are not used in all C compilers, code using these keywords may not be portable.

The special keywords related to addressing are __near, __far, __huge, and __based.

The special keywords related to calling conventions are __cdecl, __fortran, __pascal, __stdcall, and __fastcall.

These keywords modify the meaning of variable and function declarations. When a special keyword appears in a declarator, it modifies the item immediately to the right of the keyword.

You can apply more than one special keyword to the same item. For example, you might modify a function identifier with both the __far keyword and the __pascal keyword. In this case, the order of the keywords does not matter (that is, __far __pascal myvar and __pascal __far myvar have the same effect). Thus the “binding” characteristics of the special keywords are the same as those of the type specifiers const and volatile except that const and volatile bind to the left and the keywords such as __far bind to the right. (“Type Qualifiers” contains descriptions of the const and volatile keywords.)

Using Address-Related Keywords

The __near, __far, __huge, and __based keywords modify either objects or pointers to objects. If an object identifier is to the right of the keyword, the keyword determines if the object will be allocated in the default data segment or in a separate data segment. If a pointer is to the right of the keyword, the keyword determines whether the pointer will hold a near, based, far, or huge address. Examples using these keywords appear in “Using the Special Keywords”.

You can override the default addressing convention for a given function, function call, or data reference by declaring code or data items as near, far, huge, or based. You don't need to change the addressing conventions for the program as a whole if you use the __near, __far, __huge, or __based keyword.

The following list summarizes the characteristics of data defined with these keywords. See “Function Attributes” for additional information on using these keywords in function declarations.

__near

Data resides in the default data segment, _DATA. It is referenced with 16-bit addresses (near pointers to data are 16 bits), so data addressed can be in the default segment only. Variables declared with the __near keyword use 16-bit pointer arithmetic.

32-Bit Specific

The 32-bit compiler does not allow the use of the __near keyword.¨

__far

Data can be anywhere in memory. It is not assumed to reside in the current data segment. Data items are referenced with 32-bit addresses (far pointers to data are 32 bits). Data objects declared as far must reside within the segment in which they start. Therefore, they must be smaller than 64K. Variables declared with the __far keyword use 16-bit pointer arithmetic.

32-Bit Specific

The 32-bit compiler does not allow the use of the __far keyword.¨

__huge

Data can be anywhere in memory. It is not assumed to reside in the current data segment. Individual arrays can exceed 64K in size. Data is referenced with 32-bit addresses (huge pointers to data are 32 bits). The __huge keyword is not applicable to functions. Variables declared with the __huge keyword use 32-bit pointer arithmetic for data (same restrictions as for arrays specified with the __huge keyword). Objects declared as huge trade efficiency in pointer arithmetic for relaxed limits on array and object size. Objects with automatic storage class cannot be declared as huge.

32-Bit Specific

The 32-bit compiler does not allow the use of the __huge keyword.¨

__based

Data can be anywhere in memory. It is not assumed to reside in the current data segment. The range of 32-bit addresses is provided by 16-bit addresses plus a programmer-provided base. A based pointer is a 16-bit value interpreted as an offset from a supplied base. Variables declared with the __based keyword use 16-bit pointer arithmetic for data. See “Based Pointers” for more information on __based.

The __based keyword is recommended instead of the alloc_text pragma for specifying the location of a function. However, the alloc_text pragma is still supported.

32-Bit Specific

For 32-bit targets, __based specifies that a pointer is a 32-bit offset from a 32-bit base.¨

Using Calling-Convention-Related Keywords

These modifiers are placed before the function name and can appear before or after the __near, __far, __huge, or __based modifiers. This list explains each of the keywords used to specify calling conventions. These keywords begin with two underscores. See “Identifiers” for information about this ANSI naming convention.

__pascal, __fortran

Specifies that the associated function is to be called using the Pascal or FORTRAN calling convention (arguments are pushed from left to right). The __fortran and __pascal modifiers are synonyms.

32-Bit Specific

The __fortran and __pascal keywords are not accepted for 32-bit targets.¨

__cdecl

Specifies that the associated function is to be called using the normal C calling convention (arguments are pushed from right to left). Use this specifier with individual functions if the /Gc compiler option may have been set to make the Pascal/FORTRAN calling convention the default. This is the default for 16-bit targets.

32-Bit Specific

The __cdecl calling convention is the default for 32-bit targets.¨

__fastcall

Specifies that the function uses a calling convention that passes arguments in registers rather than on the stack, resulting in faster code. The __fastcall calling convention cannot be used with functions having variable-length parameter lists, or functions having any of the following attributes: __export, __interrupt, __saveregs. The 16-bit compiler uses the AX, BX, and DX registers, but Microsoft reserves the right to change the registers and implementation of the __fastcall calling convention between releases of the compiler.

32-Bit Specific

The 32-bit compiler uses the ECX and EDX registers, but Microsoft reserves the right to change the registers and implementation of the __fastcall calling convention between releases of the compiler.¨

32-Bit Specific

__stdcall

Specifies that the arguments of the designated function are pushed right to left, that an underscore is prepended to the name, and that an at-sign character (@) followed by the number of bytes in the argument list is appended to the name (called “name decoration”). The __stdcall calling convention is only available for 32-bit targets.¨

__export

Specifies that the compiler should place information in the object file to show that the symbol is exported from a dynamic-link library (DLL) to Microsoft WindowsÔ.

Nonstatic variables defined with the __pascal keyword cannot be distinguished by case. For example, the following two variables have external linkage and the compiler resolves them to one variable:

int __pascal A;

int __pascal a;

However, the following two definitions have internal linkage and the compiler resolves them to two distinct variables:

static int __pascal A;

static int __pascal a;

See “Function Attributes” for more information on function calling conventions.

Data Declarations with the __based Keyword

Static and external objects can be declared using the __based keyword. In this context, the __based specification causes the object to be allocated in the specified segment. See Chapter 4 of Programming Techniques for more information.

To specify the segment for storing data, you can use the built-in function __segname. This function accepts a string literal and returns a value of type __segment. The code looks like this:

__segname( string-literal )

This declares a based variable by giving a segment constant as a base. The string-literal can be the name of one of four predefined segments (_CODE, _CONST, _DATA, or _STACK), or it can be the name of a new segment you define.

External data based on seg_expr, a segment variable of type __segment, has the form

extern type __based( seg_expr )

Data declared this way resides in a location determined at run time. You can re-locate a segment in memory, set seg_expr to the new location of that segment, and access a variable stored in that segment without using pointers.

Data based on the address of another variable has the form

__based( (__segment)&var )

The var specified must itself be based on a named segment. This declaration places both variables in the same segment.

32-Bit Specific

The __segment and __segname keywords are not available with the 32-bit compiler.¨

Using the Special Keywords

This section provides examples of how to use the special keywords. You can use two or more special keywords in different parts of a declaration to modify the meaning of the declaration. For example, the following declaration contains occurrences of the __far and __near keywords:

int __far * __pascal __near func( void );

In this example, the __pascal and __near keywords modify the function identifier func. The return value of func is declared to be a far pointer to an int value.

As in any C declaration, you can use parentheses to override the default interpretation of the declaration. The rules governing complex declarators (discussed in “Interpreting More Complex Declarators”) also apply to declarations that use the special keywords. The memory model determines the default size for pointers. This can be specified with the command-line options /AL, /AS, /AM, and /AH, or (within PWB) by selecting the memory model in the C Compiler Options dialog box.

int __huge database[65000];

This example declares a huge array named database with 65,000 int elements. The __huge keyword modifies the array declarator.

char * __far * x;

char * (__far *x);

In these statements, the __far keyword modifies the asterisk to its right, making x a far pointer to a pointer to char. The second statement is an alternative way to write this declaration that can make your code easier to read.

double __near __cdecl calc( double, double );

double __cdecl __near calc( double, double );

Since the special keywords can be used in any order, these two declarations are equivalent. Both declare calc as a function with the __near and __cdecl attributes.

char __far __fortran initlist[INITSIZE];

char __far *nextchar, __far *prevchar, __far *currentchar;

In the two declarations above, the first declares a __far __fortran array of characters named initlist, and the second declares three far pointers named nextchar, prevchar, and currentchar. These pointers might be used to store the addresses of characters in the initlist array. Note that the __far keyword must be repeated before each declarator.

char __far *(__far *getint)( int __far * );

^ ^ ^ ^ ^ ^

6 5 2 1 3 4

This example shows a more complex declaration with several occurrences of the __far keyword. The numbers indicate the order in which the declaration is interpreted in the following procedure:

1.The identifier getint is declared as a

2.__far pointer to

3.a function taking

4.a single argument, that is, a __far pointer to an int value

5.and returning a __far pointer to a

6.char value.

Note that the __far keyword always modifies the item immediately to its right. “Interpreting More Complex Declarators” provides more information about interpreting complex declarators.