11

This feels like a really stupid thing to ask, but I had someone taking a programming class ask me for some help on an assignment and I see this in their code (no comments on the Hungarian notation please):

void read_dictionary( string ar_dictionary[25], int & dictionary_size ) {...

Which, as mainly a C# programmer (I learned about C and C++ in college) I didn't even know you could do. I was always told, and have read since that you're supposed to have

void read_dictionary( string ar_dictionary[], int ar_dictionary_size, int & dictionary_size ) {...

I'm told that the professor gave them this and that it works, so what does declaring a fixed size array like that even mean? C++ has no native way of knowing the size of an array being passed to it (even if I think that might've been changed in the newest spec)

cost
  • 4,420
  • 8
  • 48
  • 80
  • It has native way to know the array size: this method. If you tell it how great the array is, it will believe it is. –  Apr 29 '12 at 04:58
  • 2
    The `25` in the parameter declaration is ignored by the compiler. It's the same as `string ar_dictionary[]`. – Cody Gray - on strike Apr 29 '12 at 04:59
  • 1
    @H2CO3 There is nothing the function can do with that number, nor any way for the compiler to check if what is being passed to it is that size... – cost Apr 29 '12 at 05:05
  • @CodyGray Oh is that what it is? That would make the most sense, given what I know about C++. I never even tried that syntax, I figured the compiler would throw an error. Can you say that in an answer so I can mark that as the answer? – cost Apr 29 '12 at 05:06
  • let me give you a trick: If you do `void func(int (&myarr)[25]);` arrays of size not 25 will be refused. message from gcc: ` error: invalid initialization of reference of type 'int (&)[25]' from expression of type 'int [3]'` – v.oddou Feb 27 '15 at 09:48
  • It's curious that one of the people who answered this question 7 years ago now marked this as duplicate, some 7 years later. – cost Apr 15 '19 at 20:57

3 Answers3

13

In a one dimensional array It has no significance and is ignored by the compiler. In a two or more dimensional array It can be useful and is used by the function as a way to determine the row length of the matrix(or multi dimensional array). for example :

int 2dArr(int arr[][10]){
   return arr[1][2];
}

this function would know the address of arr[1][2] according to the specified length, and also the compiler should not accept different sizes of arrays for this function -

int arr[30][30];
2dArr(arr);

is not allowed and would be a compiler error(g++) :

error: cannot convert int (*)[30] to int (*)[10]
WeaselFox
  • 7,220
  • 8
  • 44
  • 75
  • What do you mean the function would know the address? – cost Apr 29 '12 at 05:30
  • 1
    accessing the array at [x][y] means accessing the element at row y and column x. for this you have to know what is the length of the row. `arr[1][2]` is the same as `arr[2*10 + 1]`. – WeaselFox Apr 29 '12 at 07:59
6

The 25 in the parameter declaration is ignored by the compiler. It's the same as if you'd written string ar_dictionary[]. This is because a parameter declaration of array type is implicitly adjusted to a pointer to the element's type.

So the following three function declarations are equivalent:

void read_dictionary(string ar_dictionary[25], int& dictionary_size)
void read_dictionary(string ar_dictionary[],   int& dictionary_size)
void read_dictionary(string *ar_dictionary,    int& dictionary_size)

Even in the case of the first function, with the size of the array explicitly declared, sizeof(ar_dictionary) will return the same value as sizeof(void*).

See this sample on Codepad:

#include <string>
#include <iostream>

using namespace std;

void read_dictionary(string ar_dictionary[25], int& dictionary_size)
{
    cout << sizeof(ar_dictionary) << endl;  
    cout << sizeof(void*) << endl;  
}

int main()
{
    string test[25];
    int dictionary_size = 25;
    read_dictionary(test, dictionary_size);

    return 0;
}

Output (the exact value is, of course, implementation-dependent; this is purely for example purposes):

4
4
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 1
    Does WeaselFox's answer make any sense to you? If it's just decayed to a pointer, then what he said shouldn't be true. I'm a bit confused – cost Apr 29 '12 at 05:31
  • In the first one, sizeof(ar_dictionary) will return sizeof(void*) too? – Spidey Apr 29 '12 at 05:31
  • 1
    Arrays with multiple dimensions work differently than those with a single dimension. I'm not sure what that has to do with anything; the question only concerns one-dimensional arrays. @cos – Cody Gray - on strike Apr 29 '12 at 08:36
  • @Spidey: Yes. Added an example to my answer. – Cody Gray - on strike Apr 29 '12 at 08:39
  • There are actually two different rules in play here. One is that an expression of array type, in most contexts, is implicitly converted to ("decays" to) a pointer to the array's first element. The other is that a parameter declaration of array type is *adjusted* to a pointer to the element type. The language *could* have had either rule without the other, but it has both. They work together to -- well, to cause confusion. – Keith Thompson Apr 29 '12 at 08:58
2

I always though that passing fixed size C++ arrays was a "half baked" feature of C++. For example, ignored size matching or only being able to specify the first index size, etc... Until recently I learn this idiom:

template<size_t N1, size_t N2> // enable_if magic can be added as well
function(double(&m)[N1][N2]){
  ... do something with array m...knowing its size!
}

Reference: Can someone explain this template code that gives me the size of an array?

Community
  • 1
  • 1
alfC
  • 14,261
  • 4
  • 67
  • 118