1

Possible Duplicate:
How to find the sizeof(a pointer pointing to an array)

In the first call to strcpy_s the compiler can deduce the array length, but in the second call the array length has to be passed in.

TCHAR szTemp[512];
::strcpy_s(szTemp, "a long text message");

TCHAR* pszTemp = new TCHAR[512];
::strcpy_s(pszTemp, 512, "a long text message");
delete []pszTemp;

How does the compiler do this? Is this a Microsoft only extension? Also, how could I declare my methods to take advantage of the parameter deduction?

Community
  • 1
  • 1
Joseph King
  • 5,089
  • 1
  • 30
  • 37
  • 1
    @BoPersson: This question is not a duplicate of that one since this question asks how the size is deduced in certain cases, and the other one does not. – Eric Postpischil Dec 12 '12 at 20:14
  • 2
    @Eric - It's all about the difference between an array and a pointer. Same problem. – Bo Persson Dec 12 '12 at 20:15
  • @BoPersson: No, it is not “all” about the difference between an array and a pointer. It asks about deducing the size, and that issue is not asked about in the other question, and it is not discussed except in the fourth-ranked answer, which does not explain its example. – Eric Postpischil Dec 12 '12 at 20:18
  • 1
    The compiler does not *deduce* the size of arrays, it **knows** because you told it. A better wording for the question would be something along the lines of *How does the function know the size of the array?* – David Rodríguez - dribeas Dec 12 '12 at 20:27

5 Answers5

6

In the first use of strcpy_s, the number of elements in the array szTemp is part of the type of szTemp (since it is an “array of 512 TCHAR”), so the compiler knows about it and can complete the template that declares strcpy_s.

In the second use of strcpy_s, pszTemp is a pointer (it is a “pointer to TCHAR”), not an array, and the number of elements pointed to is not part of the type. In general, a compiler cannot know how many elements are at the place where a pointer points. (In this case, a compiler might deduce it, since the preceding code shows it, but that adds complications to the compiler and the language that are generally regarded to be not worth implementing.)

To do this yourself, declare a template the way strcpy_s is declared:

template <size_t size> errno_t strcpy_s(
    char (&strDestination)[size],
    const char *strSource 
); 

This declares a template based on parameter size, and the template is for a function whose first parameter has the type “reference to an array of size elements of char”. When the compiler sees the use of strcpy_s with a first argument that is an array of 512 elements of char, it is able to match this argument to the parameter in the template, and it deduces that size is 512.

Somewhere else, you will have a definition of the template (not just a declaration). That definition can use the template parameter size in its code. When the compiler sees the use of strcpy_s, it will instantiate the template definition in a specialization where size is 512.

This only works in C++, not C, because C does not have templates.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
2

According to docs, strcpy_s exists as a concrete function, but also as a template function overloaded for arrays of known size, such as the szTemp array you provide. In that case the size of the array is the template parameter of the function definition.

strcpy_s is itself a Microsoft-only function, so the template version is no more Microsoft-specific than the version that accepts a pointer.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
1

The first is using a template, something like:

template <size_t N>
strcpy_s(char (&dest)[N], char const *source) { 
    // ...
}

Inside the template, N is the size of the array that was passed.

In your second case, pszTemp is a pointer instead of an array, so it won't match up with the template parameter (which requires an actual array), so you need to pass the destination size explicitly.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

In the first case the template function is used (doc), so there's no magic:

template <size_t size>
errno_t strcpy_s(
   char (&strDestination)[size],
   const char *strSource 
); // C++ only
alekseyk
  • 133
  • 9
1

It can deduce the array length for szTemp because it is declared as an array. For pszTemp, it is declared as a pointer and there is no way to deduce its length.

There are supposedly some third party strcpy_s implementations, but mostly it is a Microsoft thing--it was part of their effort to harden up their security holes.

Joseph Willcoxson
  • 5,853
  • 1
  • 15
  • 29