Использование размера одного массива в другом массиве - PullRequest
8 голосов
/ 30 сентября 2010
// 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;
}

Я слышал, что размер массива в C ++ должен быть константным выражением.Так что char q[size(p)] недействительно, я прав?Но я не получил ошибок при попытке

 g++ -Wall sizeofarray.cpp

Почему?

Ответы [ 4 ]

7 голосов
/ 30 сентября 2010

Как и Прасун говорит: , это не постоянное выражение. На данный момент вы можете получить значение константного выражения размера массива, например:

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))

Объяснение здесь . Вы в основном кодируете размер массива в размер типа, а затем получаете sizeof этого типа, давая вам:

char q[sizeof_array(p)];
4 голосов
/ 30 сентября 2010

Я слышал, что размер массива в C ++ должен быть константным выражением.

Правильно

Значит, символ q [размер (p)] недействителен, я прав?

В соответствии с ISO C ++, да!

Но я не получил ошибок при попытке

g ++ -Wall sizeofarray.cpp

Это потому, что g ++ поддерживает VLA ( Массив переменной длины ) в качестве расширения.

В C++0x имеется функция constexpr с помощьюкоторый вы можете написать

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

, а затем char q[size(p)] будет допустимым.

РЕДАКТИРОВАТЬ : также прочитайте эту статью [блог как угодно]

0 голосов
/ 30 сентября 2010

Я использую g ++ 4.4.3 и имею следующий псевдоним, чтобы я никогда не забывал включать предупреждения:

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

Если скомпилировано с вышеупомянутым, будут некоторые предупреждения. Следующие шаги показывают, как разные опции показывают разные предупреждения.

Компиляция без опции предупреждения не показывает никаких предупреждений

$ \g++ sizeofarray.cpp 

Включение -Wall

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

Включение -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’

Наконец-то включив -pedantic, чтобы поймать реальную проблему

$ \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’
0 голосов
/ 30 сентября 2010

Прошу не согласиться со всеми ответами здесь. Шоу кода прекрасно, за исключением незначительной проблемы (которая определенно не 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; 
} 

Мне было интересно, что результат sizeof всегда является константным значением, и, следовательно, код должен быть в порядке.

Приведенный выше код прекрасно работает на VS 2010 и Comeau (строгий режим)

$ 5.3.3 / 6- "Результатом является константа введите size_t. [Примечание: размер_t определен в стандартном заголовке (18.1). "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...