4
// sizeofarray.cpp
#include <iostream>
template <typename T,int N>
int size(T (&Array)[N])
{
  return N;
}

int main()
{
   char p[]="Je suis trop bon, et vous?";
   char q[size(p)]; // (A)
   return 0;
}

I heard that an array size in C++ must be a constant expression. So char q[size(p)] is invalid, am I right? But I got no errors when I tried

 g++ -Wall sizeofarray.cpp

Why?

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
Ideone
  • 41
  • 1

4 Answers4

4

I heard that an array size in C++ must be a constant expression.

Correct

So char q[size(p)] is invalid, am I right?

According to ISO C++, yes!

But I got no errors when I tried

g++ -Wall sizeofarray.cpp

That's because g++ supports VLA (Variable Length Array) as an extension.

In C++0x there is constexpr feature with the help of which you can write

constexpr int size(T (&Array)[N])
{
  return N;
}

and then char q[size(p)] would be legal.

EDIT : Also read this article [blog whatever]

Community
  • 1
  • 1
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 1
    surely sizeof is a constant expression(atleast for a non-vla which standard C++ doesn't even have) ? – nos Sep 30 '10 at 13:55
4

Like Prasoon says, it's not a constant expression. For now, you can get a constant-expression value of the size of an array like this:

template <std::size_t N>
struct type_of_size
{
    typedef char type[N];
};

template <typename T, std::size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]);

#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray))

Explanation here. You basically encode the size of the array into the size of a type, then get the sizeof of that type, giving you:

char q[sizeof_array(p)];
Community
  • 1
  • 1
GManNickG
  • 494,350
  • 52
  • 494
  • 543
-1

I beg to differ with all the answers here. The code show is perfectly fine except for a minor issue (which is definitely not VLA)

template <typename T,int N> 
int size(T (&Array)[N]) 
{ 
  return N; 
} 

int main() 
{ 
   char p[]="Je suis trop bon, et vous?"; 
   char q[sizeof(p)]; // (A), not sizeof and not size as in OP
   return 0; 
} 

I was wondering that the result of the sizeof is always a const value, and hence the code should be fine.

The above code builds fine on VS 2010 and Comeau(strict mode)

$5.3.3/6- "The result is a constant of type size_t. [Note: size_t is defined in the standard header (18.1)."

Chubsdad
  • 24,777
  • 4
  • 73
  • 129
-1

I use g++ 4.4.3 and have the following alias so that I never forget to turn on the warnings:

$ alias g++
alias g++='g++ -ansi -pedantic -Wall -W -Wconversion -Wshadow -Wcast-qual -Wwrite-strings'

If compiled with the above, there would be some warnings. Following steps show how different options show different warnings.

Compilation with no warning option does not show any warning

$ \g++ sizeofarray.cpp 

Turning on -Wall

$ \g++ -Wall sizeofarray.cpp
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: unused variable ‘q’

Turning on -Wextra

$ \g++ -Wall -Wextra sizeofarray.cpp 
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: unused variable ‘q’
sizeofarray.cpp: At global scope:
sizeofarray.cpp: In instantiation of ‘int size(T (&)[N]) [with T = char, int N = 27]’:
sizeofarray.cpp:12:   instantiated from here
sizeofarray.cpp:4: warning: unused parameter ‘Array’

Finally turning on -pedantic to catch the real problem

$ \g++ -Wall -Wextra -pedantic  sizeofarray.cpp 
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: ISO C++ forbids variable length array ‘q’
sizeofarray.cpp:12: warning: unused variable ‘q’
sizeofarray.cpp: At global scope:
sizeofarray.cpp: In instantiation of ‘int size(T (&)[N]) [with T = char, int N = 27]’:
sizeofarray.cpp:12:   instantiated from here
sizeofarray.cpp:4: warning: unused parameter ‘Array’
Arun
  • 19,750
  • 10
  • 51
  • 60