Specifying Managed Arrays as Function Parameters in C++

Welcome to this week's installment of .NET Tips & Techniques! Each week, award-winning Architect and Lead Programmer Tom Archer from the Archer Consulting Group demonstrates how to perform a practical .NET programming task.

If you've been developing applications using the .NET Managed Extensions to C++, you've no doubt run into the peculiar syntax regarding defining arrays as input and output parameters to and from functions. To refresh your memory, look at some examples of defining functions that receive and return arrays.

The Standard Way

Here's an example of a function that takes an array of reference types (String objects):

// Function that takes an array of reference types
void PassArrayOfReferenceTypes(String* strings[])
{
}

// calling code
String* ar1[] = new String*[5];
PassArrayOfReferenceTypes(ar1);

Note that the type precedes the variable name with square brackets appended to the variable name. The number of dimensions is then specified by inserting commas between the brackets—one comma for two dimensions, two commas for three dimensions, and so on.

Now, look at the syntax involved in passing an array of value types (int) to a function:

// Function that takes an array of value types
void PassArrayOfValueTypes(int numbers __gc[])
{
}

// calling code
int ar2 __gc[] = new int __gc[5];
PassArrayOfValueTypes(ar2);

Take special note of the insertion of the __gc keyword. The reason for this is that while the array members are value types, the array itself is a reference type. Hence, the need for the __gc keyword.

Finally, let's look at how to define a function that returns an array. In native (non-.NET) C++, arrays are returned from a function to the caller via a pointer to the array's first element. With Managed Extensions, the array type and dimensions are both specified in the function's signature. The following example function illustrates a function that returns a two-dimensional array of int value objects:

int ReturnArray() [,]
{
   int values[,] = new int __gc [2,4];    // 2x4 array

   ...

   return values;
}

// calling code
int ar3 [,] = ReturnArray();

Note that the type precedes the function name and the brackets (indicating an array of that type) follows the closing parenthesis of the functions argument list. Commas are then used within the brackets to indicate the number of dimensions the array will contain.

A More Intuitive Way

We're all professionals here and can learn to adapt to any new syntax that gets thrown our way. However, with just a couple of type definitions and a macro, we can make our code much more readable and intuitive. For example, instead of having to remember to use the __gc keyword with arrays of value type members, we can simply define a typedef for each desired type so that we can use the same syntax for either reference or value types. From there, we can specify a generic macro that takes the type name as a parameter so we don't have to remember the name of the typedef for each supported type. Here's how that would look:

#define MCArray(type) type##Array
typedef int intArray __gc[];
typedef String* StringArray [];
// .. add more typedefs here per your needs

Now, compare the following function signatures, standard Managed Extensions syntax vs. the MCArray macro:

// Returning arrays using the Standard Managed Extensions syntax
int ReturnInt1() __gc[]
String* ReturnString1() []

// Returning arrays using the MCArray macro
MCArray(int) ReturnInt2()
MCArray(String) ReturnString2()

// Passing arrays using the Standard Managed Extensions syntax
void PassArrayOfReferenceTypes(String* strings[])
void PassArrayOfValueTypes(int numbers __gc[])

// Passing arrays using the MCArray macro
void PassArrayOfReferenceTypes(MCArray(String) values)
void PassArrayOfValueTypes(MCArray(int) values)

As you can see, MCArray macro provides several benefits, including the following:

  • You don't have to remember which types require the pointer specification.
  • You don't have to remember which types require the __gc keyword.
  • You don't have to remember to place the square brackets nor where to place them.

In summary, the MCArray is much closer to native C++ syntax, resulting in fewer mistakes and greater readability.



About the Author

Tom Archer - MSFT

I am a Program Manager and Content Strategist for the Microsoft MSDN Online team managing the Windows Vista and Visual C++ developer centers. Before being employed at Microsoft, I was awarded MVP status for the Visual C++ product. A 20+ year veteran of programming with various languages - C++, C, Assembler, RPG III/400, PL/I, etc. - I've also written many technical books (Inside C#, Extending MFC Applications with the .NET Framework, Visual C++.NET Bible, etc.) and 100+ online articles.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Instead of only managing projects organizations do need to manage value! "Doing the right things" and "doing things right" are the essential ingredients for successful software and systems delivery. Unfortunately, with distributed delivery spanning multiple disciplines, geographies and time zones, many organizations struggle with teams working in silos, broken lines of communication, lack of collaboration, inadequate traceability, and poor project visibility. This often results in organizations "doing the …

  • Live Event Date: April 22, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Database professionals — whether developers or DBAs — can often save valuable time by learning to get the most from their new or existing productivity tools. Whether you're responsible for managing database projects, performing database health checks and reporting, analyzing code, or measuring software engineering metrics, it's likely you're not taking advantage of some of the lesser-known features of Toad from Dell. Attend this live …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds