Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Вопрос по динамическим массивам

Ответить
Настройки темы
C/C++ - Вопрос по динамическим массивам

Аватара для nikit-xxx

Старожил


Сообщения: 320
Благодарности: 20


Конфигурация

Профиль | Отправить PM | Цитировать


Изменения
Автор: nikit-xxx
Дата: 12-05-2011
Объясните пожалуйста разницу между
Код: Выделить весь код
int b[4][5][6];
и
Код: Выделить весь код
int i, j;

	int ***b;
	b = (int***) malloc(4 * sizeof(int**));
	for(i = 0; i < 4; i++){
		b[i] = (int**) malloc(5 * sizeof(int*));
		for(j = 0; j < 5; j++){
			b[i][j] = (int*) malloc(6 * sizeof(int));
		}
	}
Спрашиваю потому что:
читать дальше »

Следующий код не компиллится, если в формальном параметре 3-х мерный массив объявить "обычным" способом (закомментировано):
пишет ошибку: строка 23 | error: cannot convert 'int***' to 'int (*)[5][6]' for argument '1' to 'void test_function(int (*)[5][6])'

Код: Выделить весь код
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

void test_function(int ***e);
//void test_function(int e[][5][6]); //- вот так не компиллится

int
main(void)
{
	int i, j;

	int ***b;
	b = (int***) malloc(4 * sizeof(int**));
	for(i = 0; i < 4; i++){
		b[i] = (int**) malloc(5 * sizeof(int*));
		for(j = 0; j < 5; j++){
			b[i][j] = (int*) malloc(6 * sizeof(int));
		}
	}
	b[2][3][4] = -123;

	test_function(b);

	printf("b[2][3][4] = %d\n", b[2][3][4]);

	getch();
	return(0);
}

void
test_function(int ***e)
/*void
test_function(int e[][5][6])*/ // вот так не компиллится
{
    ;
}

-------
справочник по BIOS


Отправлено: 18:42, 09-05-2011

 

Старожил


Сообщения: 154
Благодарности: 39

Профиль | Отправить PM | Цитировать


разница в способе выделения памяти.

в первой цитате под переменную b будет выделено последовательно 4*5*6 полей int. последовательных. обязательно ровно 4*5*6 чтобы не случилось.

во второй цитате память выделяется динамически. сначала выделяется ячейка памяти размером 4*int** и ее адрес записывается в b(тройной указатель). Затем в цикле в кусок размером int** (двойной указатель) хранящемуся по адресу b[i] (то что было выделено ранее) записывается адрес вновь выделяемого куска памяти размером 5*int*. В каждый кусочек по адресу b[i][j] мы записываем адрес вновь выделяемой ячейки памяти размером 6*int. И того получаем у нас 4 двойных указателя, каждый из которых хранит адрес 5-и указателей, которые указывают на 6*int памяти.

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

на счет ошибки
В теле мейна ты своей функции подсовываешь тройной указатель. А в объявлении функции ты говоришь о какомто непойми e[][5][6] который явно не тройной указатель. учи английский ))
Это сообщение посчитали полезным следующие участники:

Отправлено: 19:42, 10-05-2011 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для nikit-xxx

Старожил


Сообщения: 320
Благодарности: 20

Профиль | Отправить PM | Цитировать


сообщение компилятора на английском мне было понятно, я просто думал что объявление массива в первой цитате и массива во второй цитате - одно и тоже. Да терь понимаю, что во второй цитате указатель на указатель на указатель на тип int.
Спасибо.

-------
справочник по BIOS


Отправлено: 22:04, 10-05-2011 | #3


Аватара для nikit-xxx

Старожил


Сообщения: 320
Благодарности: 20

Профиль | Отправить PM | Цитировать


Кстати, а в Кернигане говорится что
Цитата:
Следующие две формы эквивалентны, если употребляются в виде формальных
параметров функции:
char s [] ;
char *s;


Ещё вопрос по функциям malloc / free:
Код: Выделить весь код
int *t;
t = (int*) malloc(5);
картинка с моими предположениями:


Теперь t указывает на самую первую ячейку памяти, отведённую для типа int ?
Тогда откуда free(t) узнает сколько ячеек следует освободить?

-------
справочник по BIOS


Отправлено: 20:39, 12-05-2011 | #4


Старожил


Сообщения: 198
Благодарности: 51

Профиль | Отправить PM | Цитировать


malloc является системным вызовом, он запрашивает память в куче у ОС.
free также является системным вызовом, он освобождает участок памяти в куче.
ОС хранит информацию о выделенной памяти в своих внутренних структурах, к которым оно и обращается при вызове malloc , free, таким образом ОС знает сколько памяти надо освободить.
t = (int*) malloc(5); - выделит лишь 5 байт, а вам надо t = (int*) malloc(5*sizeof(int)); - 5 элементов типа int (на 32бит архитектуре - 20 байт)
Цитата nikit-xxx:
Теперь t указывает на самую первую ячейку памяти, отведённую для типа int ? »
Именно так.
Это сообщение посчитали полезным следующие участники:

Отправлено: 21:59, 12-05-2011 | #5


ИО Капитана Очевидности


Contributor


Сообщения: 5387
Благодарности: 1105

Профиль | Отправить PM | Цитировать


В первом случае память выделяется в стеке последовательно - идентификатор массива представляет собой "указатель первого порядка" (int *), а доступ к элементу одномерного массива осуществляется через сложение индексов (I = I1 + I2*N2 + I3*N3)
Во втором случае память выделяется в стеке отдельными блоками - идентификатор массива представляет собой "указатель третьего порядка" (int ***), а доступ к элементу массива осуществляется через последовательное обращение по адресам указателей (к I1-му элементу массива указателей второго порядка, оттуда к I2-му элементу массива указателей первого порядка, а уже оттуда к I3-му элементу )

Цитата nikit-xxx:
пишет ошибку: строка 23 | error: cannot convert 'int***' to 'int (*)[5][6]' for argument '1' to 'void test_function(int (*)[5][6])' »
Для использования статического массива (вариант 1) нужно объявить функцию void test_function(int *array[5][6]) - это позволит программе правильно вычислять индекс для указателя array [i1][i2][i3] по известным "размерам" .

А вот если объявить функцию void test_function (int array [4][5][6]), то произойдёт копирование статического массива в функцию. Понятно, что передавать объекты большого размера крайне нежелательно (занимает "много" времени, да и стэк - не резиновый). Это делается, если в процессе работы функции переданный объект изменится, в то время как оригинальный массив меняться не должен.
Если же изменений не будет, то можно передать объект константной ссылкой test_function (const int &array [4][5][6])

И самое главное, никогда не задавай границы массивов цифрами - только через константы
Код: Выделить весь код
const int sizeA = 4; 
const int sizeB = 5; 
const int sizeC = 6; 
................. 
int Array [sizeA][sizeB][sizeC];
Если использовать обычные цифры, то при изменении размера в одном месте программы можно легко забыть изменить его в другом.

P.S.
Цитата PhilB:
t = (int*) malloc(5); - выделит лишь 5 байт, а вам надо t = (int*) malloc(5*sizeof(int)); - 5 элементов типа int (на 32бит архитектуре - 20 байт) »
Для выделения памяти под массивы можно также использовать функцию calloc с двумя параметрами (размер элемента, кол-во элементов) или оператор new []

Цитата PhilB:
malloc является системным вызовом, он запрашивает память в куче у ОС.
free также является системным вызовом, он освобождает участок памяти в куче.
ОС хранит информацию о выделенной памяти в своих внутренних структурах, к которым оно и обращается при вызове malloc , free, таким образом ОС знает сколько памяти надо освободить. »
Между прочим, операторы new (new[]) и delete (delete[]) используют несколько другие вызовы, чем функции malloc-realloc-free.

-------
Самое совершенное оружие, которым забиты арсеналы богатых и процветающих наций, может легко уничтожить необразованного, больного, бедного и голодного. Но оно не может уничтожить невежество, болезнь, нищету и голод. (Фидель Кастро)

Почему всех осужденных за измену Родине при Сталине реабилитировали при Горбачёве по отсутствию состава преступления? Потому что при Горбачёве измену Родине перестали считать преступлением.

Это сообщение посчитали полезным следующие участники:

Отправлено: 03:46, 13-05-2011 | #6



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Вопрос по динамическим массивам

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Delphi - [решено] Задачка по массивам vovan1993 Программирование и базы данных 5 14-04-2011 13:25
Router - Проблема с динамическим IP <TP-Link TL-WR340G> frozee Сетевое оборудование 3 17-06-2010 03:09
[решено] DNS сервер с динамическим IP адресом Dosmod Microsoft Windows NT/2000/2003 7 30-08-2009 22:58
Проблема с динамическим диском MoRoman Microsoft Windows NT/2000/2003 8 05-06-2006 16:03
Настройка доступа к машине с динамическим адресом... Guest Сетевые технологии 2 29-03-2004 21:35




 
Переход