Microsoft-Specific Modifiers

Post date: Apr 29, 2011 10:24:45 AM

1. __based Keyword

The __based keyword allows you to declare pointers based on pointers (pointers that are offsets from existing pointers).

type __based( base ) declarator  

Pointers based on pointer addresses are the only form of the __based keyword valid in 32-bit or 64-bit compilations. For the Microsoft 32-bit C/C++ compiler, a based pointer is a 32-bit offset from a 32-bit pointer base. A similar restriction holds for 64-bit environments, where a based pointer is a 64-bit offset from the 64-bit base.

One use for pointers based on pointers is for persistent identifiers that contain pointers. A linked list that consists of pointers based on a pointer can be saved to disk, then reloaded to another place in memory, with the pointers remaining valid. For example:

// based_pointers2.cpp // compile with: /EHsc #include <iostream>  int a1[] = { 1,2,3 }; int a2[] = { 10,11,12 }; int *pBased;  typedef int __based(pBased) * pBasedPtr;  using namespace std; int main() {    pBased = &a1[0];    pBasedPtr pb = 0;     cout << *pb << endl;    cout << *(pb+1) << endl;     pBased = &a2[0];     cout << *pb << endl;    cout << *(pb+1) << endl; }

1 2 10 11

2. _cdecl

This is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code. The following list shows the implementation of this calling convention.

struct CMyClass {    void __cdecl mymethod(); };

this

void CMyClass::mymethod() { return; }

is equivalent to this

void __cdecl CMyClass::mymethod() { return; }

Place the __cdecl modifier before a variable or a function name. Because the C naming and calling conventions are the default, the only time you need to use __cdecl is when you have specified the /Gz (stdcall) or /Gr (fastcall) compiler option. The /Gd compiler option forces the __cdecl calling convention.

For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention specified during declaration is assumed at the point of definition. Given this class definition,

3. __declspec

The extended attribute syntax for specifying storage-class information uses the __declspec keyword, which specifies that an instance of a given type is to be stored  with a Microsoft-specific storage-class attribute listed below. Examples of other

storage-class modifiers include the static and extern keywords. However, these keywords are part of the ANSI specification of the C and C++ languages, and as such are not covered by extended attribute syntax. The extended attribute syntax simplifies and standardizes Microsoft-specific extensions to the C and C++ languages.

he dllexport, dllimport, naked, noalias, nothrow, property, restrict, selectany, thread, and uuid storage-class attributes are properties only of the declaration of the object or function to which they are applied. The thread attribute affects data and objects only. The naked attribute affects functions only. The dllimport and dllexport attributes affect functions, data, and objects. The property, selectany, and uuid attributes affect COM objects.

The __declspec keywords should be placed at the beginning of a simple declaration. The compiler ignores, without warning, any __declspec keywords placed after * or & and in front of the variable identifier in a declaration.

A __declspec attribute specified in the beginning of a user-defined type declaration applies to the variable of that type. For example:

__declspec(dllimport) class X {} varX;

In this case, the attribute applies to varX. A __declspec attribute placed after the class or struct keyword applies to the user-defined type. For example:

class __declspec(dllimport) X {};

In this case, the attribute applies to X.

The general guideline for using the __declspec attribute for simple declarations is as follows:

decl-specifier-seq declarator-list;

The decl-specifier-seq should contain, among other things, a base type (e.g. int, float, a typedef, or a class name), a storage class (e.g. static, extern), or the __declspec extension. The init-declarator-list should contain, among other things, the pointer part of declarations. For example:

__declspec(selectany) int * pi1 = 0;   //OK, select any & int both part of decl-specifier 

int __declspec(selectany) * pi2 = 0;   //OK, select any & int both part of decl-specifier 

int * __declspec(selectany) pi3 = 0;   //ERROR, select any is not part of a declarator

The following code declares an integer thread local variable and initializes it with a value:

// Example of the __declspec keyword __declspec( thread ) int tls_i = 1;

4. __fastcall

The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when possible. The following list shows the implementation of this calling convention.

Using the /Gr compiler option causes each function in the module to compile as fastcall unless the function is declared with a conflicting attribute, or the name of the function is main.

On Itanium Processor Family (IPF) and AMD64 machines, __fastcall is accepted and ignored by the compiler; on an IPF chip, by convention, parameters are passed in register.

For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention specified during declaration is assumed at the point of definition. Given this class definition,

 struct CMyClass {    void __fastcall mymethod(); };

this

void CMyClass::mymethod() { return; }

is equivalent to this

void __fastcall CMyClass::mymethod() { return; }

In the following example, the function named DeleteAggrWrapper is passed arguments in registers:

// Example of the __fastcall keyword #define FASTCALL    __fastcall     void FASTCALL DeleteAggrWrapper(void* pWrapper); // Example of the __ fastcall keyword on function pointer typedef BOOL (__fastcall *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, 

...);

__restrict

Like the restrict __declspec modifier, the __restrict keyword indicates that a symbol is not aliased in the current scope. The __restrict keyword differs from the restrict __declspec modifier in the following ways:

Generally, if you affect the behavior of an entire function, it is better to use the __declspec than the keyword.

__restrict is similar to restrict from the C99 spec, but __restrict can be used in C++ or C programs.

There is no support for __restrict on C++ references.

// __restrict_keyword.c // compile with: /LD // In the following function, declare a and b as disjoint arrays // but do not have same assurance for c and d. void sum2(int n, int * __restrict a, int * __restrict b,            int * c, int * d) {    int i;    for (i = 0; i < n; i++) {       a[i] = b[i] + c[i];       c[i] = b[i] + d[i];     } }  // By marking union members as __restrict, tell compiler that // only z.x or z.y will be accessed in any given scope. union z {    int * __restrict x;    double * __restrict y; };

__stdcall

The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype.

For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention specified during declaration is assumed at the point of definition. Given this class definition,

struct CMyClass {    void __stdcall mymethod(); };

this

void CMyClass::mymethod() { return; }

is equivalent to this

void __stdcall CMyClass::mymethod() { return; }

In the following example, use of __stdcall results in all WINAPI function types being 

handled as a standard call:

// Example of the __stdcall keyword #define WINAPI __stdcall // Example of the __stdcall keyword on function pointer typedef BOOL (__stdcall *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, ...);

__w64

(Microsoft Specific) Lets you mark variables, such that when you compile with /Wp64 the compiler will report any warnings that would be reported if you were compiling with a 64-bit compiler.

type __w64 identifier

// __w64.cpp // compile with: /W3 /Wp64 typedef int Int_32;

#ifdef _WIN64 typedef __int64 Int_Native; #else typedef int __w64 Int_Native; #endif  int main() {    Int_32 i0 = 5;    Int_Native i1 = 10;    i0 = i1;   // C4244 64-bit int assigned to 32-bit int     // char __w64 c;  error, cannot use __w64 on char }

__unaligned

When you declare a pointer with the __unaligned modifier, the compiler assumes that the pointer addresses data that is not aligned. Consequently, for an application that targets an Itanium Processor Family (IPF) computer, the compiler generates code that reads the unaligned data one byte at a time.

// unaligned_keyword.cpp // compile with: /c // processor: x64 IPF #include <stdio.h> int main() {    char buf[100];     int __unaligned *p1 = (int*)(&buf[37]);    int *p2 = (int *)p1;     *p1 = 0;   // ok     __try {       *p2 = 0;  // throws an exception    }    __except(1) {       puts("exception");    } }

-Courtesy Microsoft