int x;
cin >> x;
const int y = x;
foo(y);
Условие выхода из цикла, если не известна длина массива.
Код:
const char * FunctionArray[]=
{"Function1","Function2","Function3","Function4"}
{"Function1","Function2","Function3","Function4"}
Для константных массивов можно получать размер используя sizeof(массив)/sizeof(тип элемента).
:)
Код:
...
int i = 0;
do {
cout << FunctionArray[i] << endl;
} while ((FunctionArray[i++])[8] != '4');
...
int i = 0;
do {
cout << FunctionArray[i] << endl;
} while ((FunctionArray[i++])[8] != '4');
...
Код:
int i = 0;
while(FunctionArray[i])
std::cout << FunctionArray[i++] << std::endl;
while(FunctionArray[i])
std::cout << FunctionArray[i++] << std::endl;
Таких массивов просто не должно быть. Если есть что-то, по чему надо пробегаться, то это что-то должно хранить свой размер. Получать его где-то как-то и передавать с собой. Если есть что-то, что не имеет размера, то оно не используется для обработок, а только для передачи из одного места в другое.
Может ТС просто думал, что определить длину си-строки можно только по нуль-терминатору. Отсюда столь странный вопрос :)
Цитата: sadovoya
Может ТС просто думал, что определить длину си-строки можно только по нуль-терминатору. Отсюда столь странный вопрос :)
Вот это уже интереснее. А как ещё её можно определить? :)
Код:
char c_str[] = "C-String";
const int len_without_0 = sizeof(c_str)/sizeof(char) - 1;
cout << "The length without null-terminator is " << len_without_0 << endl;
const int len_without_0 = sizeof(c_str)/sizeof(char) - 1;
cout << "The length without null-terminator is " << len_without_0 << endl;
Точняк. Совсем забыл об этой фиче.
Компилятор -- он лапочка, сам посчитает за нас размерность для незаполненных [ ] при инициализации. Моя любимая фишка с массивами :)
А передачу такой "строки" в функцию разве все с++ компиляторы одобрят? Включая старые. Кажется, всё равно придётся с поинтером работать на каком-нибудь старье.
Либо шаблоны параметризировать размерами, либо куча иных решений.
Не передадут, но его так же можно получить твоим способом.
А вы строку поменяйте (кстати для вашего примера 3 - неверный ответ, должен быть 4). На самом деле в вашей функии sizeof(x) = числу байт адреса (4) Теперь понимаете?
Это не мой пример. :)
вот тут те-же 3 выводится (и так будет всегда, с любой строкой на всех машинах с 4-байтными адресами)
Ну
What a heck? То есть, для инициализированного массива компилер смог получить длину, а для переданного в функцию затрудняется?
Статический массив имеет привилегию при инициализации не указывать размерность - компилятор сам способен ее вычислить по перечню в { }. Откуда такой подарок -- не знаю. Типичней случай, когда он за нас нефига не делает. Я бы сказал проще - ф-ции, принимающие массивы трактуют их как указатели. Иначе скрытно надо разменость либо где-то помнить, либо вычислять. Возможны накладные расходы, а С++ в плане эффективности щепетилен.
Интересно узнать, какие ещё есть профиты от этой способности вычислять размерность массива. Кроме как упрощённой инициализации. Похоже на костыль.
Думаю, что упрощенная инициализация -- весь профит. Ну, хоть вручную считать размер не надо.
Код:
void foo(int count){
sometype Array[count];
//...
}
sometype Array[count];
//...
}
Код:
void foo(const int count);
Запрет понятен. Для статического массива размер должен быть даже не просто константа, а константа известная на момент компиляции.
Вдруг мы делаем что-то типа такого:
Код:
Получается, что нестандартное поведение реализуется на самом деле так:
Код:
void foo(int count){
sometype *Array = new sometype [count];
//...
delete [] Array;
}
sometype *Array = new sometype [count];
//...
delete [] Array;
}
Короче, знайте, что такие штуки непереносимы между компиляторами. Лучше включить в настройках компилятора оповещения об нестандартных конструкциях.
Вообще, странно присваивать константной переменной значение другой неконстантной переменной. Информация интересная. И давно gcc начал такое разрешать? Не с 11-го ли стандарта?
Стандарт C++11 тоже вряд ли такое разрешил. Это все самодеятельность gcc, его "расширения" языка так сказать. Расширениями не только он балуется. Просто в настройках компилятора надо следование стандарту установить, либо не устанавливать. Я теперь всегда ставлю по крайней мере опцию "оповещать" о нестандартности кода.
Код:
void foo(const int count) {
int Array[count];
//...
}
int main() {
foo(5);
return 0;
}
int Array[count];
//...
}
int main() {
foo(5);
return 0;
}
Соображает и с шаблонами на предмет известности констант на момент компиляции:
Код:
#include <iostream>
template<int count>
void foo() {
int Array[count];
//...
}
int main() {
int x;
std::cin >> x;
const int c = x;
foo<c>(); //не скомпилируется !!!
const int d = 5;
foo<d>(); //нормально
return 0;
}
template<int count>
void foo() {
int Array[count];
//...
}
int main() {
int x;
std::cin >> x;
const int c = x;
foo<c>(); //не скомпилируется !!!
const int d = 5;
foo<d>(); //нормально
return 0;
}
P.S.
Вообще, странно присваивать константной переменной значение другой неконстантной переменной.
CassandraDied, это вы о чем?
в C99). Может я не прав, и в С++ они тоже появились, а вовсе это не самодеятельность gcc... Одно ясно, что для совместимости со старыми стандартами их не следует использовать. Да и механизм их не очень ясен.
Оказывается стандарт Си разрешил массивы переменной длины (
Цитата: sadovoya
CassandraDied, это вы о чем?
Я бы никогда не стал инициализировать константу какой-либо переменной. Даже, если она является аргументом функции. Обычно константам присваивается вычисленное на месте значение.
Цитата: sadovoya
Оказывается стандарт Си разрешил массивы переменной длины (в C99). Может я не прав, и в С++ они тоже появились, а вовсе это не самодеятельность gcc... Одно ясно, что для совместимости со старыми стандартами их не следует использовать. Да и механизм их не очень ясен.
Чёткие парни в энтерпрайзе не пользуются массивами. Только контейнеры, только автоматическое высвобождение памяти!
CassandraDied, в обоих ваших высказываниях не от шарпа ли что? :)
И я начинаю склоняться к мысли, что в большинстве случаев действительно можно избежать использования массива или динамически выделенной памяти, которая потом будет использоваться, как массив. А если бы ещё и с++1х использовать, с их новой move семантикой и достаточно быстрыми новыми умными указателями, то от использования массивов можно отказаться ещё в большем спектре решаемых задач.
Да можно, конечно. Есть еще Java с уборкой мусора тоже.
Просто C++ тем и хорош, что сочетает высокий уровень и низкий.