Консультация № 191233
20.07.2017, 15:47
0.00 руб.
0 33 1
Уважаемые эксперты! Пожалуйста, ответьте на вопрос: почему не будет работать цикл для диапазона внутри приведенной ниже функции для обработки массива неизвестного размера вместо того, что там сейчас?

Код:
//функция displayArray - отображает элементы массива
//integerArray длиной sizeOfloatArray
void displayArray (int integerArray[], int sizeOfloatArray)
{
for (int i = 0; i < sizeOfloatArray; i++)
{
cout << i << ": " << integerArray [i] << endl;
}
}


Ведь размер массива будет передан в функцию...

Обсуждение

давно
Посетитель
7438
7205
20.07.2017, 16:39
общий
Адресаты:
Странное имечко sizeOfloatArray выбрано
Тогда уж лучше sizeOfArray
Надо стараться использовать имена, которые говорят о своем содержимом.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401172
78
20.07.2017, 16:58
общий
Цитата: Лысков Игорь Витальевич
Странное имечко sizeOfloatArray выбрано

Действительно странно, тем более в программе, откуда кусок я выдернула используются одни int-ы, это из книги Стефана Р.Дэвиса "С++ для чайников"
Сейчас напишу поподробнее.
Тема "Циклы для диапазонов".
давно
Посетитель
401172
78
20.07.2017, 17:10
общий
Речь идет о новинке C++ '11 (сейчас уже не новинка, конечно).
Написано, что в ряде случаев можно обратится к элементам массива с помощью цикла for для диапазонов, и приведен пример, в котором цикл инициализирует все элементы массива nArray значением 0:
Код:
int nArray[128];
for (int& n: nArray)
{
n=0;
}

Все прекрасно (хотя верим на слово, т.к. мой компилятор о такой новинке не в курсе, судя по сразу выданной ошибке), но далее написано, что этот цикл можно использовать только тогда, когда С++ знает размер массива во время построения программы. Таким образом, например в функции displayArray (копирую ниже), цикл работать не будет.
Код:
//функция displayArray - отображает элементы массива
//integerArray длиной sizeOfloatArray
void displayArray (int integerArray[], int sizeOfloatArray)
{
for (int i = 0; i < sizeOfloatArray; i++)
{
cout << i << ": " << integerArray [i] << endl;
}
}

Вот и думаю - почему? Ведь размер будет известен...
давно
Советник
400484
472
20.07.2017, 17:20
общий
Цитата: pNod
Все прекрасно (хотя верим на слово, т.к. мой компилятор о такой новинке не в курсе, судя по сразу выданной ошибке), но далее написано, что этот цикл можно использовать только тогда, когда С++ знает размер массива во время построения программы. Таким образом, например в функции displayArray (копирую ниже), цикл работать не будет.
Код :: выделить код
//функция displayArray - отображает элементы массива
//integerArray длиной sizeOfloatArray
void displayArray (int integerArray[], int sizeOfloatArray)
{
for (int i = 0; i < sizeOfloatArray; i++)
{
cout << i << ": " << integerArray [i] << endl;
}


Возможно, не будет работать, если передаваемый массив будет динамически формироваться. Т.е. длина массива будет изменяться во время работы программы...
давно
Посетитель
7438
7205
20.07.2017, 17:29
общий
Адресаты:
Хм, о циклах для диапазонов не слышал. Сам сижу на старом компиляторе. Разберемся.

Теперь по сути вопроса.
В первом случае, все верно, размер массива известен во время компиляции.
Во втором же параметром передается не массив, как таковой, а указатель на начало массива.
Размер его, действительно, неизвестен.
Второй параметр для компилятора - простое целое, никак не связанное с массивом.
Неважно, что мы интерпретируем его, как размер массива...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401172
78
20.07.2017, 17:37
общий
Цитата: solowey
Возможно, не будет работать, если передаваемый массив будет динамически формироваться. Т.е. длина массива будет изменяться во время работы программы...


Так вроде параметрами для этого и пользуются, а не конкретным, выраженным числом размером массива...
Допустим сменилось количество, но в функцию то оно при обращении к ней снова передаваться будет, и на экран выведутся уже новые данные...
Может об этом не надо задумываться, а просто принять как данность?
давно
Посетитель
7438
7205
20.07.2017, 17:40
общий
У меня есть несколько версий MSC++. Самая новая - MS C++10.0

Не подскажете, где в ней включить поддержку C++11
Или в этой версии этого еще нет?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401172
78
20.07.2017, 17:43
общий
Цитата: Лысков Игорь Витальевич
Второй параметр для компилятора - простое целое, никак не связанное с массивом.
Неважно, что мы интерпретируем его, как размер массива...


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


давно
Посетитель
401172
78
20.07.2017, 17:50
общий
Цитата: Лысков Игорь Витальевич
У меня есть несколько версий MSC++. Самая новая - MS C++10.0


У меня Dev-C++ 4.9.9.2, поставленная по совету автора этой книги специально для ее изучения, и все примеры из книги по идее должны в ней работать .
Про MS не подскажу, еще не сталкивалась.
давно
Посетитель
7438
7205
20.07.2017, 18:18
общий
Адресаты:
Получается, что в цикле для диапазонов мы можем указать только имя массива, которое является его же адресом, а второй параметр эта новинка просто не содержит?
Если размер задан во время компиляции, то компилятор знает его размер и формирует цикл до указанного значения.
В случае же динамического массива, а задание указателя - фактически и есть динамический массив, его размер в момент компиляции неизвестен, поэтому цикл для диапазонов здесь не работает.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401172
78
20.07.2017, 18:35
общий
Игорь Витальевич, может задам очень простой вопрос, но я меня, похоже, сформировались неправильные понятия о сборке программы.
Я считала, что компилятор собирает построчно сверху-вниз с выполнением запрашиваемых в теле main функций...ну и с подключением библиотек.
Например, если мы делаем динамический массив, компилируется и выполняется до места определения массива, далее пользователь вводит этот массив, например, с клавиатуры, затем компилируется дальше (при уже известных данных), не так?
давно
Академик
20764
1861
20.07.2017, 18:41
общий
Адресаты:
Вас, часом, не про такое спросили?
Код:
#include <iostream>

template<typename T, size_t SZ>
void pr_arr(const T (&a)[SZ]) {
for (size_t i = 0; i < SZ; i++)
std::cout << a[i] << ::std::endl;
}

int main () {
int ia[] = {1,6,7,2,8,5,9};
double fa[] = {.1,.6,.7,.2,.8,.5,.9};

pr_arr(ia);
pr_arr(fa);
return 0;
}
давно
Посетитель
401172
78
20.07.2017, 19:06
общий
Цитата: Хватов Сергей
Вас, часом, не про такое спросили?

Меня не спросили, я книгу пытаюсь осилить по С++

Я заинтересовалась возможностью посимвольного вывода с помощью for для диапазонов, вместо обычного, в котором надо делать
Цитата: Хватов Сергей
i = 0; i < SZ; i++
в динамических массивах.
Но уже понимаю, что дело в самой форме нововведения, которая просто этого не предусматривает, а существует как инструмент для инициализированных массивов.
давно
Посетитель
7438
7205
20.07.2017, 19:17
общий
Адресаты:
не так?
Конечно, не так. Программный код формируется сразу из текста программы.
Получаем файл программы EXE. Запускаем. Ну или среда запускает...

Что-то известно сразу во время компиляции, типа констант. А под что-то только резервируется место, типа адреса динамического массива.
Сам массив, адреса его элементов станут известны только во время выполнения.
Динамический массив - он потому динамический, что строится по ходу дела.
Ну и если в подпрограмму передается адрес массива, то этот адрес фактически является адресом динамического массива.

Так, как Вы описали, работают интерпретаторы. Это в них происходит работа построчно. Читается строка текста, выполняется и т.д.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
20.07.2017, 19:29
общий
Адресаты:
Сергей, может Вы знаете ответ на мой вопрос выше в посту №10
Давно хотел приобщиться к С++11, да все как-то особой нужды не было.
А тут вот заинтересовался.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401172
78
20.07.2017, 19:37
общий
Ок, тогда посмотрите, пожалуйста, все ли правильно понимаю порядок :
1) сразу при сохранении кода - исходный текст программы - файл с расширением .cpp
2) компиляция - перевод в машинный код исходного текста .obj
3) выполнение - создаем исполняемый файл .exe - получается здесь уже собираются модули, подключаются библиотеки и формируются динамические массивы?
давно
Посетитель
7438
7205
20.07.2017, 19:42
общий
20.07.2017, 19:43
Адресаты:
Чуток поправлю
1) сразу при сохранении кода - исходный текст программы - файл с расширением .cpp - да!
2) компиляция - перевод в машинный код исходного текста .obj - да!
добавим линковку
3) линковка - создаем исполняемый файл .exe - собираются модули, подключаются библиотеки. Получаем .exe
исправляем
4) выполнение - запускаем исполняемый файл .exe - работает программа, в ходе выполнения, если надо, формируются динамические массивы
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401172
78
20.07.2017, 19:49
общий
Спасибо
давно
Академик
20764
1861
21.07.2017, 12:03
общий
Адресаты:
Не знаю: у меня Linux, а в нём gcc, который уже и C++14 поддерживает.
давно
Посетитель
7438
7205
21.07.2017, 12:13
общий
Адресаты:
Точно, я и забыл...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Академик
20764
1861
21.07.2017, 12:30
общий
Адресаты:
Вот это работать будет, более простые варианты - нет:
Код:
template<typename T, size_t SZ>
void pr_arr(const T (&a)[SZ]) {
for (const T &p: a)
std::cout << p << ::std::endl;
}
причём SZ здесь обязателен, хотя он вроде бы не используется. Естественно, настоящий указатель в такую функцию передавать нельзя, о чём сразу же заявит компилятор.

Вообще, for (TYPE value: pointer) - это всего лишь syntax sugar для перебора коллекции с помощью методов begin(), ++ и end()
Ну, и особый, но ограниченный случай для перебора элементов массива
давно
Посетитель
7438
7205
21.07.2017, 14:19
общий
Адресаты:
Мне кажется, это можно и в ответ записать...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Академик
20764
1861
21.07.2017, 14:39
общий
Адресаты:
только я так и не понял, чего хотела автор вопроса. Тем более, что формальный ответ очень короткий: "Этот код работать будет" :)
давно
Посетитель
7438
7205
21.07.2017, 14:46
общий
Адресаты:
Она хотела понять, почему не будет работать код в вопросе, если попытаться заменить его на цикл для диапазонов, если в функцию передается указатель на массив и отдельно длина массива.
Вроде разобрались (пост №16). Но ответ надо дать. Тем более, Ваш пример достаточно интересен.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Академик
20764
1861
21.07.2017, 15:17
общий
это ответ
Здравствуйте, pNod!

С помощью дополнительных вопросов выяснилось, что вас интересует цикл, перебирающий коллекцию:
Код:
for(auto &element: collection) {...}

На самом деле это всего лишь syntax sugar (русского термина не знаю) для классического перебора:
Код:
for auto (pointer = collection->begin();pointer!=collection->end();pointer++){auto &element = *pointer;...}

Есть особый случай: такой цикл можно применять для массивов, но только если их размер известен компилятору. Можно даже в inline функции использовать (хотя это уже трюкачество). Вот пример с кое-какими комментариями:
Код:
#include <iostream>

// SZ в функции не встречается, но он всё равно необходим!
template<typename T, size_t SZ>
void pr_arr(const T (&a)[SZ]) {
for (const T &p: a)
std::cout << p << ::std::endl;
}
int main () {
static const int ia[] = {1,6,7,2,8,5,9};
static const double fa[] = {.1,.6,.7,.2,.8,.5,.9};
pr_arr("Hello, world!");
pr_arr(ia);
pr_arr(fa);

int n=10; // const int n=10 исправит проблему, но это, вероятно, уже оптимизация так работает :)
int a[n]; // такое уже допустимо
for (auto &b: a) b = 3;
//pr_arr(a); // а это не пройдёт компиляцию: размер массива компилятору неизвестен

return 0;
}


5
давно
Мастер-Эксперт
425
4118
29.07.2017, 04:54
общий
Адресаты:
Dev-C++ 4.9.9.2 - это старина несусветная, где в комплекте используется GCC (набор компиляторов C\C++) производства 2004 года. Так что, сами понимаете, никакго С++11 там нет.
Другое дело, если Вы ставите DevC++ без компилятора, тогда компилятор нужно ставить отдельно (например MinGW) и в этом случае, если ставить последнюю версию компилятора, он будет поддерживать C++11.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Мастер-Эксперт
425
4118
29.07.2017, 05:01
общий
Адресаты:
Цитата: Лысков Игорь Витальевич
У меня есть несколько версий MSC++. Самая новая - MS C++10.0

Не подскажете, где в ней включить поддержку C++11

Скорее всего нигде, т.к. даже MSC++10-SP1 датирована мартом 2011 года. А вот в MSC++12 высока вероятность, что сие работает по умолчанию. А уж в MSC++14...
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Посетитель
401172
78
29.07.2017, 14:48
общий
Цитата: Вадим Исаев ака sir Henry
Dev-C++ 4.9.9.2 - это старина несусветная

Да, я поняла уже.
Я поставила эту версию по рекомендации автора книги по С++, которую планирую осилить до конца.
Якобы все примеры разбирались в этой в версии и работают.
Затем буду искать среду или отдельно компилятор с поддержкой последних нововведений.
давно
Посетитель
7438
7205
31.07.2017, 11:06
общий
Адресаты:
Скорее всего нигде
Я уже и сам понял.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Мастер-Эксперт
425
4118
31.07.2017, 18:54
общий
31.07.2017, 18:55
Адресаты:
Одно из двух: либо Вы не поняли автора (возможно он имел в виду только установку IDE), либо автора не понял переводчик.
К сожалению на сегодняшний день качество переводов плохое. Если раньше на каждого автора (и переводчика в том числе) приходилось по 5..7 редакторов\корректоров, то сегодня на одного редактора по 200...300 авторов. Главная задача издательств не обеспечить страждущих информацией, а побыстрей закинуть макулатуру в продажу.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Форма ответа