Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.53/120: Рейтинг темы: голосов - 120, средняя оценка - 4.53
 Аватар для Vahram1995
1 / 1 / 1
Регистрация: 20.01.2013
Сообщений: 80

Передача по ссылке двумерного динамического массива в функцию

24.12.2015, 05:01. Показов 24197. Ответов 114
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приведите, пожалуйста, пример. Нигде не могу найти.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
24.12.2015, 05:01
Ответы с готовыми решениями:

Передача двумерного массива в функцию по ссылке
Требуется написать функцию, которая выделяет память для одномерного и двумерного динамического массива. Для первого варианта вопросов вроде...

Передача динамического двумерного массива в функцию
Я сделал вот так: void PrintMatrix(int** matrix, int& n, int& m) { for (int i = 0; i < n; i++) { cout << "Row "...

Передача двумерного динамического массива в функцию
Как можно передать динамическую матрицу в функцию что бы при выходе из функции она оставила прежние значения?

114
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
26.12.2015, 13:36
Студворк — интернет-сервис помощи студентам
У тебя тогда все адреса того, что там уже есть, сместятся. В стеке что-то выделяется только при вызове функции.
Эта нестандартная возможность некоторых компиляторов - просто завуалированный new.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
26.12.2015, 14:21
Цитата Сообщение от nmcf Посмотреть сообщение
Эта нестандартная возможность некоторых компиляторов - просто завуалированный new.
Не всегда. См. сюда: http://man7.org/linux/man-pages/man3/alloca.3.html
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
26.12.2015, 14:38
Цитата Сообщение от nmcf Посмотреть сообщение
У тебя тогда все адреса того, что там уже есть, сместятся. В стеке что-то выделяется только при вызове функции.
Эта нестандартная возможность некоторых компиляторов - просто завуалированный new.
Сам придумал?
Возьмем LLVM и откроем занятный файлик, например, x86 архитектуры (как самой знакомой тебе) - lib/Target/X86/X86FrameLowering.cpp. Там среди прочего лежит реализация функционала генерации пролога и эпилога вызываемой функции (надеюсь не надо объяснять, что это). И что же мы видим:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// hasFP - Return true if the specified function should have a dedicated frame
/// pointer register.  This is true if the function has variable sized allocas
/// or if frame pointer elimination is disabled.
bool X86FrameLowering::hasFP(const MachineFunction &MF) const {
  const MachineFrameInfo *MFI = MF.getFrameInfo();
  const MachineModuleInfo &MMI = MF.getMMI();
  const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
 
  return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
          RegInfo->needsStackRealignment(MF) ||
          MFI->hasVarSizedObjects() ||
          MFI->isFrameAddressTaken() || MFI->hasInlineAsmWithSPAdjust() ||
          MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() ||
          MMI.callsUnwindInit() || MMI.callsEHReturn());
}
Очевидно, что оптимизация frame pointer elimination не будет проводиться при variable sized allocas, у нас будет два указателя - один на начало фрейма, другой - на верх стека.

Находим в генерации пролога это:
C++
1
2
3
4
5
6
7
8
9
10
11
// If we need a base pointer, set it up here. It's whatever the value
  // of the stack pointer is at this point. Any variable size objects
  // will be allocated after this, so we can still use the base pointer
  // to reference locals.
  if (RegInfo->hasBasePointer(MF)) {
    // Update the base pointer with the current stack pointer.
    unsigned Opc = Is64Bit ? X86::MOV64rr : X86::MOV32rr;
    BuildMI(MBB, MBBI, DL, TII.get(Opc), BasePtr)
      .addReg(StackPtr)
      .setMIFlag(MachineInstr::FrameSetup);
  }
И в генерации эпилога:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// If dynamic alloca is used, then reset esp to point to the last callee-saved
  // slot before popping them off! Same applies for the case, when stack was
  // realigned.
  if (RegInfo->needsStackRealignment(MF) || MFI->hasVarSizedObjects()) {
    if (RegInfo->needsStackRealignment(MF))
      MBBI = FirstCSPop;
    if (CSSize != 0) {
      unsigned Opc = getLEArOpcode(IsLP64);
      addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr),
                   FramePtr, false, -CSSize);
    } else {
      unsigned Opc = (Is64Bit ? X86::MOV64rr : X86::MOV32rr);
      BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
        .addReg(FramePtr);
    }
  }
Ну тут как бы все ясно.

Можно еще взглянуть, как подчищаются псевдоинструкции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
if (!reseveCallFrame) {
    // If the stack pointer can be changed after prologue, turn the
    // adjcallstackup instruction into a 'sub ESP, <amt>' and the
    // adjcallstackdown instruction into 'add ESP, <amt>'
    // TODO: consider using push / pop instead of sub + store / add
    if (Amount == 0)
      return;
 
    // We need to keep the stack aligned properly.  To do this, we round the
    // amount of space needed for the outgoing arguments up to the next
    // alignment boundary.
    unsigned StackAlign =
        MF.getTarget().getFrameLowering()->getStackAlignment();
    Amount = (Amount + StackAlign - 1) / StackAlign * StackAlign;
 
    MachineInstr *New = nullptr;
    if (Opcode == TII.getCallFrameSetupOpcode()) {
      New = BuildMI(MF, DL, TII.get(getSUBriOpcode(IsLP64, Amount)),
                    StackPtr)
        .addReg(StackPtr)
        .addImm(Amount);
    } else {
      assert(Opcode == TII.getCallFrameDestroyOpcode());
 
      // Factor out the amount the callee already popped.
      Amount -= CalleeAmt;
 
      if (Amount) {
        unsigned Opc = getADDriOpcode(IsLP64, Amount);
        New = BuildMI(MF, DL, TII.get(Opc), StackPtr)
          .addReg(StackPtr).addImm(Amount);
      }
    }
А что же gcc? Мне лень лезть в код, но он, ествно, тоже кладет все на стек, а не через new
C++
1
2
3
4
5
6
7
8
9
10
11
#include <alloca.h>
#include <cstdint>
#include <iostream>
 
int main() {
    int* a = static_cast<int*>(alloca(999999)); // ok
    int* b = new int[999999]; // ok
    int* c = static_cast<int*>(alloca(9999999)); // Segmentation fault
    int* d = new int[9999999]; // ok
    std::cout << *a << *b << *c << *d;
}
1
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
26.12.2015, 17:38
ct0r, достаточно было сказать, что выделяется выше. Только эта "alloca" - другое. Ты же не не объявляешь массив обычным способом.
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
26.12.2015, 17:54
Цитата Сообщение от nmcf Посмотреть сообщение
Только эта "alloca" - другое. Ты же не не объявляешь массив обычным способом.
В книге было сказано, что в рантайме помимо new (что выделяет в куче), можно использовать нестандартный alloca (что выделяет на стеке). В чем разница принципиальная? Ни в чем. Отсюда вывод - ты назвал те утверждения чушью довольно опрометчиво.
Можно добавить, что то же расширение компилятора variable size array реализуется через alloca:
C++
1
int foo(int n) { int arr[n]; }
1
337 / 185 / 80
Регистрация: 22.08.2013
Сообщений: 724
26.12.2015, 18:24
Цитата Сообщение от nmcf Посмотреть сообщение
То, что на второй странице курсивом, - чушь или не корректный перевод. Не может этот массив быть в стеке.
Судя по адресам - в стеке (компилятор mingw).
Миниатюры
Передача по ссылке двумерного динамического массива в функцию  
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.12.2015, 21:35
Цитата Сообщение от gru74ik Посмотреть сообщение
Керниган, Ритчи - Программирование на C (2 издание, стр. 208)
это язык си, а не с++.

ну да ладно.
теперь давайте рассмотрим тезис:
Цитата Сообщение от gru74ik Посмотреть сообщение
Объект — это именованная область памяти;
как вы понимаете это высказывание?
что означает слово "именованная" в этом высказывании?

ну то есть понятно: что есть некая область памяти.
и у этой области есть имя.
но что это за имя? откуда оно берется?
и какое оно имеет отношение к нам, программистам?

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <string>
 
struct worker
{
    void work() {  status = "working\n"; }
    std::string status;
};
 
struct manager
{
    worker get_worker()const { return worker(); }
};
 
int main()
{
    // где здесь имя области памяти?
    manager().get_worker().work(); 
}
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
26.12.2015, 21:48
hoggy, я понимаю так:

Есть уровень абстракции, на котором уместно говорить о явлении "память, поделённая на ячейки определённого размера".
Есть уровень абстракции, на котором определённые участки памяти уместно трактовать как "объекты определённого типа". Объекты, насколько я знаю, бывают именованные и неименованные.

Что имели ввиду Керниган и Ричи - одни Боги знают. Но то, что выражение "именованная область памяти" не nord_v выдумал - это точно. Именно это я и хотел показать, когда привёл цитату.
1
337 / 185 / 80
Регистрация: 22.08.2013
Сообщений: 724
26.12.2015, 22:41
hoggy, как новое определение замечания (95 пост)?
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
26.12.2015, 23:00
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

Контекст же.
Память - это физическое устройство, способное хранить разные состояния. У таких устройств могут быть внутренние адреса.
Выборка одного или более чем одного адреса, для хранения какой-то одной сущности на время работы или вне времени работы программы порождает сущность, именуемую многими как объект. Так уж повелось издавна. Все просто, берем мое это сообщение, выдираем из него рэндомный набор символов, получаем какую-то определенную сущность. До тех пор пока эта сущность (выбранная часть) живет (в голове, на бумаге, в ПК, где угодно), она есть объект. Нет у него имени, нет у него ничего, кроме позиции относительно своего начала и внутреннего содержимого. Эта сущность (выбранная часть текста) даже не знает в каком из миров она появилась.(голова, мозги, ПК, бумага). Это - простейшая модель памяти и объекта (где весь текст - память, выбранная его часть - объект). Ничегошеньки лишнего нет. В том числе эта сущность не знает, что внутри нее какие-то там внутренности. Эта сущность просто есть. Она даже о возможностях своих не знает. Она не знает ни кому она нужна, ни зачем ее используют. Вообще ничего не знает.

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

Про именованную область памяти уместно говорить когда программист идентифицирует выбранный участок памяти каким-то именем. Именованная программистом переменная - это объект, который есть какая-то часть памяти. Это, именно, именованная программистом переменная есть именованный программистом участок памяти для удобной его обработки.

Кто бы там что не писал, надо в том числе своей головой думать, а не следовать подобно больным фанатикам всему что видим.

В то же время в третьем мире задавались вопросом: "Передача по ссылке двумерного динамического массива в функцию - C++", но почему-то в ответах темы звучали такие фразы, которые больно похожи на: "Ничто тебе уже не поможет" , а отвечики любезно забыли про ТС (очень печальная тенденция ветки С++) а сама тема переросла в холивар, в котором уже обсудили даже вовсе и не одну тему не по теме, но до сих пор эта часть не находится где-нибудь в священных войнах.
0
337 / 185 / 80
Регистрация: 22.08.2013
Сообщений: 724
26.12.2015, 23:07
Цитата Сообщение от daslex Посмотреть сообщение
а отвечики любезно забыли про ТС
Почему же забыли? Во втором посте я ему ответ дал. В 14-ом DocC привёл пример.
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
26.12.2015, 23:16
nord_v, я не буду холиварить.
Ему дали несколько ответов и тут же начали спорить. Каждый доказывая свою правоту. Басню Крылова напоминает. Пост №3 правильный ответ на тот вопрос, который написан в заголовке темы. Даже если ТС имел ввиду что-то другое, как в заголовке темы писан вопрос - так там ему и отвечено.

А указатель в С++ никогда не был массивом. Холиварить далее я не стану.
0
337 / 185 / 80
Регистрация: 22.08.2013
Сообщений: 724
26.12.2015, 23:26
Цитата Сообщение от daslex Посмотреть сообщение
Даже если ТС имел ввиду что-то другое, как в заголовке темы писан вопрос - так там ему и отвечено.
Ты на код ТС посмотри (11 пост), тогда и делай вывод: про что ТС спрашивал, и что ему надо. Я просто угадал (ещё кода не видя), что ему надо. А почему угадал: читай Прата. А код из 3-поста, к коду ТС, никаким боком не пристроишь (где там динамический массив?), потому что у ТС именно указатели. Но он, видимо, тоже читал Прата, поэтому и вопрос задал так, как Прата пишет о массивах.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
26.12.2015, 23:27
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

Цитата Сообщение от hoggy Посмотреть сообщение
как вы понимаете это высказывание?
что означает слово "именованная" в этом высказывании?
hoggy, соображения того, что в действительности в памяти только нули и единицы, наивны. Суровая реальность разбивает напрочь и утверждения, что там заряды и их отсутствия. Оказывается там только заряды. Если всё работает нормально, то заряд выше некоторого порогового трактуется как "1" и если ниже, то как "0". Остальное выдумки апологетов теории "чистого разума".

тема Передача по ссылке двумерного динамического массива в функцию
Кажется некорректной, однако, вспомним и то, что мы в разделе новичков и тут можно встретить задания вроде: "удалить из массива нечётные элементы".
Массив как способ хранения, массив как способ доступа и массив как переменная (сущность на которою можно ссылаться по ссылке), это разные вещи. В языке программистов они существуют параллельно и имеет смысл соблюдать осторожность, стараясь понять о каком значении говорит собеседник.
При первой встрече с массивами мы встречаем определение, данное с точки зрения хранения. Далее первые шаги практики показывают, что и доступ к ним особенный, то есть можно обращаться по индексу. Далее оказывается, что оператор "квадратные скобки" можно перегрузить самостоятельно и становится ясно, что доступ не всегда определяет массив, если этот доступ определён как пользовательский.
К этим трудностям ещё добавляется массив как переменная. Оказывается, что массив созданный на стеке таким образом:
C++
1
2
3
4
//somewere
const size_t N;
//---......
T some_array[N]
является полноценным типом с той точки зрения, что на него может быть создана ссылка. Это связано с тем, что компилятор знает размер такого массива.
Однако, везде и всюду существует практика называть области памяти выделенные в куче оператором new[] массивами. С точки зрения хранения тут нет проблем, они подпадают под определение. С точки зрения доступа тоже. Указатель, это встроенный тип с перегруженными скобками и это же не случайно. Указывая на начало области он не знает о её размере и предполагает доступ к первому объекту, но никто не мешает трактовать эту область как массив, обращаясь к отдельным элементам по индексу. Однако такой указатель остаётся указателем и не более. Массивом он является только в голове программиста и передача такого указателя, поддерживающая семантику массива, должна обеспечить видимость размера в область передачи дополнительными средствами.
То есть ответ на вопрос в теме:
Нельзя осуществить "Передачу по ссылке двумерного динамического массива в функцию", если под ссылкой понимать ссылку объявляемую как ссылку на массив:
C++
1
2
3
int some_array [10][20]={{123}};
int (&ref_some_array)[10][20]=some_array;
cout<<ref_some_array[0][0]<<endl;
Но в вопросе же не сказано:
"Передачу по ссылке на массив двумерного динамического массива в функцию"
Остаётся предположить, что под ссылкой имеется ввиду обобщённое название адресного выражения, под которое попадает и обычный указатель. То есть решением является передача указателя (на указатель) и двух размеров. Что и было сказано в самом начале. Прошу прощения за вторжение, с вещами, которые тут все понимают. Кроме новичков. Я с удовольствием прочел тему и часть о выделении памяти на стеке заинтересовала, как принципиальная возможность. Спасибо ct0r, надеюсь, я когда нибудь почитаю об этом побольше.
2
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
27.12.2015, 00:08
ТС получил свои ответы. И даже более того. Будем закругляться, господа.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.12.2015, 00:08
Помогаю со студенческими работами здесь

Передача двумерного динамического массива чисел в функцию
void Map::setCell(int** block, Room* room, int type){ for(int i=room-&gt;x; i&lt;room-&gt;w; ++i) for(int j=room-&gt;y; j&lt;room-&gt;h; ++j) ...

Передача двумерного динамического массива в функцию(объяснение)
Когда мы хотим передать двумерный динамический массив в функцию через указатели (**a) , то в теле ф-ии main() , мы пишем так , как указано...

Передача двумерного динамического массива в функцию в качестве параметра
Вообщем надо сложить и умножить две матрицы, но сделать это в отдельных функциях. Матрицы заданы динамическими массивами размерами n*m и...

Передача двумерного динамического массива в функцию построчно и сортировка
Всем доброго времени суток! Собственно сабж: есть двумерный динамический массив, который надо делить на одномерные и передавать в функцию...

Передача динамического двумерного массива в процедуру
Написал вот такой код для одномерного динамического массива #include &lt;iostream&gt; #include &lt;clocale&gt; using...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
115
Закрытая тема Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru