views:

206

answers:

4

I have an C++ SDK that requires a char[][512] as a parameter. I know that this is supposed to be a list of file names and the number of files could vary. For the life of me I cannot figure out how to declare this. I have an array of CStrings and I am trying to copy them over using strcpy_s and then pass them into the SDK. Any idea on how to do this?

+2  A: 

It means 2D array of char. The number of rows could vary, and it should/may be specified in another parameter. C/C++ compilers need to know the number columns when a 2D arrays is passed ,So they can build the mapping function. Simply because arrays decay to pointers when they are passed as parameters, size information is lost. For example:

void fun(char matrix[][512], int rows);
...
char matrix[100][512];
...
fun(matrix, 100);

The mapping function that the compiler construct for a 2D array is similar to:

// arrays in C/C++ are stored in Row-Major Order
matrix[i][j] == matrix[i*numberOfColumns + j]

As you can see, when a 2D array is passed and the size information is lost, we need only the number of columns to index any element in this array.

AraK
+4  A: 

This declaration has a special meaning when used to declare parameter of a function. Within the parameter list it is equivalent to char[100][512], char[123][512], char[3][512] (you get the idea - the first size can be just anything, it is simply ignored) and also to char (*)[512]. Effectively, it will accept as an argument a 2D array of chars with flexible (arbitrary) first size.

The array that you will actually pass to this function should be declared with a concrete first size, for example

char names[3][512] = { "abc", "cde", "fgh" };

if you know the first size at compile time, of course.

If the first size is only known at run time (say, n), you'll have to allocate the array dynamically

char (*names)[512] = new char[n][512];
// Now fill it with names

or, more elegantly, with a typedef

typedef char TName[512];
TName* names = new TName[n];
// Now fill it with names

I expect that the SDK function you are talking about also asks you to pass the first size of the name array as another parameter.

AndreyT
+1  A: 

Here is a way to convert an argv-style array of filenames into the form your SDK needs.

typedef char  Char512[512];

Char512 * convert(const char *names[], int n)
{
    Char512 *  arr;

    arr = new char[n][512];
    for (int i = 0;  i < n;  n++)
        ::strncpy(arr[i], names[i], 512);
    return arr;
}

When in doubt, use a typedef.

Loadmaster
'strncpy' will not work as you think it will work here. If the input array contains a name of 512 characters (or longer), you'll end up with a non-terminated string in the output array. Also, since you made that typedef ("When in doubt, use a typedef") it probably makes sense to use it in 'new' as well.
AndreyT
Yes, `strncpy()` will not terminate a target string of exactly 512 chars. The OP (and the API he's using) is probably assuming that this maximum will not be reached. But then that's a whole nuther problem to deal with.
Loadmaster
+1  A: 

Just a reminder, if you new[] something, you must delete[] (not delete) it sometime.

DevFred