[cdev] Дайджест списка рассылки cdev; том 3, выпуск 5

Grigoriy A. Sitkarev sitkarev на komitex.ru
Ср Апр 7 04:35:01 MSK 2010


Алексей Петрунёв пишет:
> Я просто потерял листок с распечаткой псевдокода где находилась ф-я
> prioq_get, так что сам немного лишнего написал. Вот, исправил:

Я кстати в список рассылки посылал псевдокод помоему. Если у тебя 
потерялась эта бумажка и ты её не откопаешь в архиве, ты мне скажи я её 
тебе перешлю, нет проблем.

> 
> struct prioq_head *
> prioq_get(struct prioq*queue)
> {
> 	struct prioq_head* head;
> 	struct user_data* ptr;
> 	unsigned int used;
> 	
> 	if (queue->used == 0) {
> 		fprintf(stderr,
> 		"prioq_get: Can't extract head from queue \n");
> 		return NULL;
> 	}
>    	head =  queue->heap[0];
> 	ptr = (struct user_data*)head;
> 	printf("data %d\n index %d\n",ptr->data,0);
> 	used = queue->used - 1;
> 	queue->heap[0] = queue->heap[used];
> 	queue->heap[0]->index = used;
> 	queue->used--;
> 	prioq_heapify(queue);
>         queue->heap[used] = NULL; 	
> 	return head;	
> }	

Я честно говоря не совсем понимаю, разве можно быть настолько 
невнимательным, Лёша?? Прежде чем посылать программу, ты должен её 
обстоятельно проверить. Здесь у тебя ошибки, ты их не хочешь сам 
поискать? Я тебе советую такой подход, ты сидишь и обстоятельно 
размышляешь, что тебе нужно написать, чётко представляя образно действия 
над указателями, массивами и т.д. Можешь налить себе чай или кофе что ты 
любишь, чтобы в этот момент тебе было комфортно. После того как ты всё 
обстоятельно обдумал т.е. имеешь чёткое представление КАК ты будешь 
писать (можно сделать зарисовки или отметки в блокноте), ты садишься за 
программу. И просто переносишь то что было у тебя обдумано в голове на 
язык программирования.

Вот смотри, даже псевдокод тебе не помог с твоим подходом (бери на 
вооружение мой). А ведь он верный. Это значит что имея псевдокод, вовсе 
не значит что не надо думать теперь. Потому что псевдокод это не 
конечная реализация пригодная к эксплуатации, а всего лишь средство 
лучше объяснить программисту как это работает.

> А почему не обуляется (в псевдокоде) указатель queue->heap[used]?  Мы
> его присваиваем  queue->heap[0], а потом сортируем в prioq_heapify
> массив состоящий уже из used-1 элементов. Но queue->heap[used] так и
> висит в памяти, когда массив уже меньше на 1.
> 

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

У меня ощущение что ты не понимаешь как Си работает с памятью а точнее, 
как в Unix процесс работает и как он получает память. NULL это значение 
адреса, которое на самом деле определено где-то так:

#define NULL	(void*(0))

Когда ты чему-то присваиваешь NULL это значит что значение указателя 
станет нулевым, т.е. в ячейке памяти, где размещено целое значение 
указателя, будет записано число 0. Это дело программиста, кому и когда 
присваивать такое значение. К управлению памятью это никакого отношения 
не имеет.

void *ptr;

ptr = malloc(12);

ptr = NULL;

Здесь я теряю значение где malloc(3) разместил 12 байт, потому что 
записал в эту переменную, где хранился адрес, число 0. Поэтому если я 
сделаю после этого так:

free(ptr);

Это будет ошибка, потому что free(3) ждёт что я ему дам тот-же адрес, 
что вернул malloc(3).

Зачем мы иногда записываем NULL? Часто чтобы обозначить что тот или иной 
указатель никуда не указывает, но это не обязательное правило. Есть 
случаи где это надо делать, есть где не надо (хотя и можно). Указатель 
это на самом деле целое число. Просто оно нас интересует не напрямую, 
как число, а как ссылка на ячейку памяти, где что-то нужное для нас 
хранится. Эта ячейка в свою очередь тоже может хранить чей-то адрес и 
т.д. до бесконечности (в теории). Хотя на практике указателей глубже чем 
char *** я никогда не встречал (это массив из массивов указателей на 
строки).

В Си (т.е. в Unix) ты сам полностью управляешь в программе где кому и 
сколько памяти было выделено и сам же возвращаешь её назад, если это 
нужно. При завершении процесса естественно что все его ресурсы 
высвобождаются, но во время работы программы никто кроме тебя за ними 
следить не будет.

Если что-то не ясно, как работает, напиши вопросы, я постараюсь ответить.

>> При ответе, пожалуйста, измение тему письма так, чтобы она была более
>> содержательной чем "Re: Содержание дайджеста списка рассылки cdev..."

Робот дело говорит кстати!

--
Г.А.




Подробная информация о списке рассылки cdev