Возврат массива функцией

Ответить

Код подтверждения
Введите код в точности так, как вы его видите. Регистр символов не имеет значения.

BBCode ВКЛЮЧЁН
[img] ВКЛЮЧЁН
[url] ВКЛЮЧЁН
Смайлики ОТКЛЮЧЕНЫ

Обзор темы
   

Развернуть Обзор темы: Возврат массива функцией

Re: Возврат массива функцией

Absurd » 31 авг 2007, 13:56

Обращение, как и было уже описано, делается с помощью raw_image->scans[j]
Выделение - с помощью alloc_raw_image(...) которую я привел.

Освобождение делается при помощи которая лежит в том же *.c файле

Код: Выделить всё

void free_raw_image(RawImage* img) {
	free(img->scans);
	free(img->raw_data);
	free(img);
}

Re: Возврат массива функцией

BBB » 31 авг 2007, 13:37

Absurd писал(а):Зачем так сложно? Можно сделать два массива - один одномерный большой, и второй одномерный маленький содержащий срез из указателей на элементы большого
Положим, это весьма спорное утверждение. В этих двух массивах вполне можно запутаться (как с обращением, так и с выделением/освобождением памяти).

Re: Возврат массива функцией

BBB » 31 авг 2007, 13:35

FLOODkOFF писал(а):да да, точно, но тогда уж и эта строчка вот так:

Код: Выделить всё

mas[i] = (char *) malloc ( (*y) * sizeof ([b]char[/b]));
Не совсем. Я, конечно, тоже описался (операция copy-paste... едрит ее :) )
Так как в итоге массив содержит int-ы, а не char-ы, то:

Код: Выделить всё

mas[i] = (char *) malloc ( (*y) * sizeof ([b]int[/b]));

Re: Возврат массива функцией

Absurd » 31 авг 2007, 11:25

BBB писал(а):Можно, кстати, вообще выделить одним куском памяти. Правда, в этом случае формально массив будет одномерный, и для обращения к элементам мссива придется "на лету" далать "преобразование" из двух "логических" координат в одну "физическую". Но зато здесь можно будет воспользоваться оператором new:

Код: Выделить всё

int* fun(int* xSize, int *ySize) //xSize, ySize -размерности
{ 
int* mas;
*xSize=10; *ySize=14//вычислили необходимые размеры

mas = new int [(*xSize) * (*ySize)]
return mas;
};
// Обращение к элементу (i, j) в этом случае будет:

mas [(i * xSize) + j]
Зачем так сложно? Можно сделать два массива - один одномерный большой, и второй одномерный маленький содержащий срез из указателей на элементы большого
Для строк писать сейчас влом, вот фрагмент программы которая работает с изображениями. Работа с пискселями: RawImage->scans[j]

.h файл

Код: Выделить всё

/*......*/
typedef struct RawImageT {
	rimg_ui4 width;
	rimg_ui4 height;
	rimg_ui2 bpp;
	rimg_byte** scans;
	rimg_byte* raw_data;
} RawImage;

rimg_error_t alloc_raw_image(int width, int height, int bpp, RawImage** out_val);
/*......*/
.c файл

Код: Выделить всё

rimg_error_t alloc_raw_image(int width, int height, int bpp, RawImage** out_val) {
	RawImage* outval0 = malloc(sizeof(*outval0));
	if (outval0) {
		rimg_byte* raw_data = 0;
		int scanlength = (width * bpp) / CHAR_BIT;
		memset(outval0, 0, sizeof(*outval0));
		if (0 != (scanlength & 3)) {
			scanlength = (scanlength | 3) + 1;
		}
		raw_data = malloc(scanlength * height);
		if (raw_data) {
			rimg_byte **scans = malloc(height * sizeof(*scans));
			if (scans) {
				int i;
				for (i = 0; i != height; ++i) {
					scans[i] = raw_data + (scanlength * i);
				}
				outval0->width = width;
				outval0->height = height;
				outval0->bpp = bpp;
				outval0->raw_data = raw_data;
				outval0->scans = scans;
				*out_val = outval0;
				return RIMG_OK;
			} else {
				free(raw_data);
				free(outval0);
				return RIMG_MEM_ERROR;
			}
		} else {
			free(outval0);
			return RIMG_MEM_ERROR;
		}
	} else {
		return RIMG_MEM_ERROR;
	}
}

Re: Возврат массива функцией

FLOODkOFF » 31 авг 2007, 10:51

BBB писал(а):

Код: Выделить всё

mas[i] = (char *) malloc ( (*y) * [B]sizeof (char *)[/B]); //<- [B]вот так верно[/B]
да да, точно, но тогда уж и эта строчка вот так:
BBB писал(а):

Код: Выделить всё

mas[i] = (char *) malloc ( (*y) * [B]sizeof (char)[/B]);

Re: Возврат массива функцией

BBB » 31 авг 2007, 10:39

FLOODkOFF писал(а):немного не так с маллоками.

Код: Выделить всё

    *x=10; //вычислили необходимые размеры
    *y=14;
    mas = (char **) malloc(*x);   // <- [b]здесь ОШИБКА[/b]
    for (int i=0; i<*x; i++)
        mas[i] = (char *) malloc(*y); // <- [b]здесь ОШИБКА[/b]
    return mas;
}
Неточность. При выделении памяти надо учитывать размер элемента массива. Учитывая, что в данном случае - сперва массив указателей, затем массив int-ов, то этот момент существенен:

Код: Выделить всё

    *x=10; //вычислили необходимые размеры
    *y=14;
    mas = (char **) malloc( (*x) * [b]sizeof (char *)[/b]);   // <- [b]вот так верно[/b]
    for (int i=0; i<*x; i++)
        mas[i] = (char *) malloc ( (*y) * [b]sizeof (int)[/b]); //<- [b]вот так верно[/b]    return mas;
}
Можно, кстати, вообще выделить одним куском памяти. Правда, в этом случае формально массив будет одномерный, и для обращения к элементам мссива придется "на лету" далать "преобразование" из двух "логических" координат в одну "физическую". Но зато здесь можно будет воспользоваться оператором new:

Код: Выделить всё

int* fun(int* xSize, int *ySize) //xSize, ySize -размерности
{ 
int* mas;
*xSize=10; *ySize=14//вычислили необходимые размеры

mas = new int [(*xSize) * (*ySize)]
return mas;
};
// Обращение к элементу (i, j) в этом случае будет:

mas [(i * xSize) + j]

Re: Возврат массива функцией

Absurd » 31 авг 2007, 10:29

Тыква писал(а):т е выходит вернуть можно только указатель на массив динамической памяти т к обычный массив будет работать только в пределах ф-ции?
Спасибо всем за ответы, немного разобрался! :)
Тебе нужен двухмерный массив строк или же одномерный массив строк, при этом ты имел в виду что каждая строка это одномерный массив char'ов?

По поводу памяти - да, локальные массивы хранятся в стеке выше адреса возврата из функции которую туда поместила инструкция call. При выходе из функции по инструкции ret массив оказывается ниже верхушки стека, в той памяти которую использовать никак нельзя.

Re: Возврат массива функцией

Тыква » 31 авг 2007, 09:56

т е выходит вернуть можно только указатель на массив динамической памяти т к обычный массив будет работать только в пределах ф-ции?
Спасибо всем за ответы, немного разобрался! :)

Re: Возврат массива функцией

FLOODkOFF » 31 авг 2007, 09:35

но как это реализовать? (в Си)
...
Ttype ** tmp = new Ttype* [n]; // наш массив...
если вы пишете на Си, то причем тут new?
P.S.
Тем не менее, ответ уже написан выше.

Re: Возврат массива функцией

FLOODkOFF » 31 авг 2007, 09:31

shurkaox писал(а):Функция должна возвращать не только указатель но и размерности массива
например так
char** fun(int* x, int *y) //x,y -размерности
{
char** mas;
*x=10; *y=14//вычислили необходимые размеры
malloc(mas, *x)//давно на С не писал, может malloc по другому маленько
for (int i=0; i<*x; i++)
malloc(mas, *y);
//теперь можно работать с mas[j]
return mas;
}
}

немного не так с маллоками.

Код: Выделить всё

char** fun(int* x, int *y)
{
    int i;
    char** mas;

    *x=10; //вычислили необходимые размеры
    *y=14;

    mas = (char **) malloc(*x);
    for (int i=0; i<*x; i++)
        mas[i] = (char *) malloc(*y); //теперь можно работать с mas[i][j]
    return mas;
}

Вернуться к началу