Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.04.2018, 01:08   #1
Александр121
Форумчанин
 
Регистрация: 17.09.2017
Сообщений: 265
По умолчанию массив динамический

1) Зачем когда обьявляем массив нужен указатель?
2) почему если массив передаётся в функцию нужен тоже указатель а не например int a;
3)почему когда массив передаётся элементы отдельно и количество отдельно а не например int *a[n];

Код:
#include <iostream>
 
void Odds(int *a, int n, int i) {
    if (i < n) {
        if (a[i] % 2 != 0)
            std::cout << a[i] << " ";
        Odds(a, n, i + 1);
    }
}
 
int main()
{
    int n; std::cin >> n;
    int *a = new int[n];
    for (int i = 0; i < n; i++) std::cin >> a[i];
    Odds(a, n, 0);
    delete[] a;
    system("pause");
    return 0;
}
Александр121 вне форума Ответить с цитированием
Старый 09.04.2018, 06:49   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

4) почему трава зелёная?
5) Почему люди не летают как птицы?
pu4koff вне форума Ответить с цитированием
Старый 09.04.2018, 18:15   #3
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Александр121 Посмотреть сообщение
1) Зачем когда обьявляем массив нужен указатель?
2) почему если массив передаётся в функцию нужен тоже указатель а не например int a;
3)почему когда массив передаётся элементы отдельно и количество отдельно а не например int *a[n];

Код:
#include <iostream>
 
void Odds(int *a, int n, int i) {
    if (i < n) {
        if (a[i] % 2 != 0)
            std::cout << a[i] << " ";
        Odds(a, n, i + 1);
    }
}
 
int main()
{
    int n; std::cin >> n;
    int *a = new int[n];
    for (int i = 0; i < n; i++) std::cin >> a[i];
    Odds(a, n, 0);
    delete[] a;
    system("pause");
    return 0;
}
1. Имя массива есть указатель на его первый элемент. Т.о. int a[20] - это по сути указатель, с распределением памяти на стеке. int *a = new int[n]; такая запись распределяет память в куче. Вся разница.
2. См. 1.
3. Потому что распределенная память не хранит информации о размере памяти. В случае записи int a[20] компилятор может "догадаться", но как только, вы использовали массив, как указатель - вся инфа уже утеряна и вы должны ее предоставить.

На стеке располагаются короткоживущие объекты, которые удаляются по завершению программной конструкции автоматически (и т.о. указатель на эту память становится не верным). Для долгоживущих объектов, которыми управляет программист - используется "куча" (через new).

Последний раз редактировалось alexzk; 09.04.2018 в 18:20.
alexzk вне форума Ответить с цитированием
Старый 10.04.2018, 00:50   #4
Александр121
Форумчанин
 
Регистрация: 17.09.2017
Сообщений: 265
По умолчанию

то есть когда работаю с массивом лучше использовать new? а стеком вообще не пользоваться?
Александр121 вне форума Ответить с цитированием
Старый 10.04.2018, 01:29   #5
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Александр121 Посмотреть сообщение
то есть когда работаю с массивом лучше использовать new? а стеком вообще не пользоваться?
причем тут луче...работать, как удобнее, для решения задачи.

Но, стек он вполне себе ограничен. На маках 512кб на все вообще, на линуксе 2мб ... т.е. да, массив байт видосика туда не влезит.

Дело еще в процессоре. Стек аппаратно быстрее раз в 20. Поэтому по времени 20 переменных на стеке = 1 переменной в куче (не точно еесно 20, но примерно). Дело в том, что стек уже распределен в момент запуска программы (потому его и мало - лимит), а для его адресации у процессора есть спец. регистр, хранящий указатель. Для кучи такого нет - вы каждый раз просите ОС выделить вам памяти - и тут все прелести - свап и прочее. Для вещей типа фотошопа, есть техники предварительной резервации (современные компиляторы тоже "втихую" там резервируют, переиспользуют, и на малых размерах ниче не заметно).
Но для 20 int эт все не важно, просто к слову о "лучше".

Последний раз редактировалось alexzk; 10.04.2018 в 01:37.
alexzk вне форума Ответить с цитированием
Старый 10.04.2018, 02:02   #6
Александр121
Форумчанин
 
Регистрация: 17.09.2017
Сообщений: 265
По умолчанию

Когда мы обращаемся к элементу массива мы прорвемся напрямую к ниму или к указателю который ведёт на этот элемент?
Александр121 вне форума Ответить с цитированием
Старый 10.04.2018, 02:13   #7
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Александр121 Посмотреть сообщение
Когда мы обращаемся к элементу массива мы прорвемся напрямую к ниму или к указателю который ведёт на этот элемент?
Цитата:
Имя массива есть указатель на его первый элемент.
Если что-то не понятно, произносите как мантру, пока осознаете Я года 2 повторял переодически...
alexzk вне форума Ответить с цитированием
Старый 10.04.2018, 03:13   #8
Александр121
Форумчанин
 
Регистрация: 17.09.2017
Сообщений: 265
По умолчанию

Cпасибо))) вот допусти код тут int *a указатель на блок памяти в котором содержится массив или на первый элемент и чем указатель на первый элемент отличается от указателя на блок памяти?

Код:
  int *a = new int[n];
Александр121 вне форума Ответить с цитированием
Старый 10.04.2018, 03:29   #9
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Александр121 Посмотреть сообщение
Cпасибо))) вот допусти код тут int *a указатель на блок памяти в котором содержится массив или на первый элемент и чем указатель на первый элемент отличается от указателя на блок памяти?

Код:
  int *a = new int[n];
Код:
указателя на блок памяти
Так вообще-то говорят в общем, т.е. void*
В вашем случае, собственно, у вас скорее блок памяти и есть. Моя мантра к стековым больше относится (int a[20]).

Это вобщем путаница из других языков. В С++ проще считать все блоками памяти и просто указателями.


И опять "но". Для стековой записи (int a[20]) инфа о блоке не вся утеряна, и можно делать трюки, например sizeof(a) даст общий размер памяти в байтах, sizeof(a[0]) даст размер элемента в байтах, а sizeof(a) / sizeof(a[0]) даст число элементов. Но это все работает, до тех пор, пока ...

Код:
int a[20];
const int *b = a;
Все, для b уже не возможно вытворять sizeof(b[0]) и sizeof(b) / sizeof(b[0]). Теперь sizeof(b) равен 4 или 8 всегда (32 или 64 бита компиляция), т.е. это размер указателя.
alexzk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Динамический массив, массив указателей alexalisa Паскаль, Turbo Pascal, PascalABC.NET 4 22.04.2011 21:33
динамический массив? gramp Microsoft Office Excel 2 26.02.2011 14:41
Динамический массив - или всё таки не динамический? vedro-compota Общие вопросы C/C++ 30 10.12.2010 23:22
Динамический массив Vito89 Помощь студентам 1 20.10.2009 01:55