PDA

Просмотр полной версии : Маленький вопросец об указателях.



versus
12.09.2004, 18:17
Вот что-то я не очень пойму если есть например такая функция:

void allocate (char** array, size_t sz) {
*array = malloc(sz);
}

не тоже ли самое будет если я напишу

void allocate (char* array, size_t sz) {
array = malloc(sz);
}

?

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

Eugie
13.09.2004, 00:42
не тоже ли самое будет если я напишу

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

versus
13.09.2004, 03:41
спасибо
дошло, хоть и не сразу
а как аналогичный примерчик выглядел бы с использование ссылок?

в голову приходит жуткая конструкция вроде char*& (или char&*)

Romeo
13.09.2004, 14:30
Первое :)

Дрюль
17.10.2004, 20:17
Ещё один маленький вопросец. Если мне нужно завести указатель на массив байтов по адресу: сегмент а000, смещение 0, это будет выглядеть так?

typedef unsigned char scrbuffer [64000];
scrbuffer *screen = (scrbuffer *)0xA000;

И ещё: прочитал в книжке Павловской, как присвоить указателю адрес памяти в явном виде. char *vp = (char *)0xB8000000 Набираю пример. Дословно. Выдаётся ошибка: cannot cast from 'unsigned long' to 'char *'. В чём косяк?

DeeJayC
18.10.2004, 13:30
Гы-гы... А какого года книжка?
Дело в том, что адрес B800:0000 - это адрес начала видеопамяти для CGA - карточек.
То есть вместо вызова прерывания на "поставить точку" будет засыл в массив. Если карточка -
баба EGA и выше, то скорее всего работать это не будет....

В данной ситуёвине надо воспользоваться FP_SEG/FP_OFF функциями. Я не исключаю, что это
это должно работать в pure-c.

Дрюль
18.10.2004, 16:46
Попробовал я использовать MK_FP, ошибка: cannot convert 'void *' to 'unsigned char[64000] *'. Может у меня руки не из того места растут? А кстати, что неправильного было в прошлом примере (scrbuffer *screen = (scrbuffer *)0xA000)? А книжка та 2003-го года :)

DeeJayC
18.10.2004, 18:01
В любом случае - под win32 это работать не должно....
Только что увидал - In Microsoft C, since the FP_SEG() and FP_OFF() macros dereference the pointer values passed to them, the address of a variable cannot be passed as a parameter. ID: Q47497

Но если очень надо указатель на адрес, только что вот такая
конструкция у меня компильнулась:



int main( int argc, char **argv ) {

char *p = (char *)0xb8000000L;
return 0;

};

Дрюль
18.10.2004, 19:06
А у меня всё равно не компилится... Может присваивание адреса можно как-нибудь ассемблерной вставкой прописать?

DeeJayC
18.10.2004, 19:09
А у меня всё равно не компилится... Может присваивание адреса можно как-нибудь ассемблерной вставкой прописать?

А какой компилятор и ось?

Дрюль
18.10.2004, 19:34
Borland C++ 3.1 и ХР

Eugie
19.10.2004, 11:11
typedef unsigned char scrbuffer [64000];
scrbuffer *screen = (scrbuffer *)0xA000;



Когда пишем такое объявление, надо понимать, что scrbuffer[0] означает весь массив unsigned char scrbuffer [64000], а не первый элемент типа unsigned char. Т.е. с точки зрения последующего посимвольного доступа такое объявление смысла не имеет. Лучше делать так:


typedef unsigned char * TScreenBuf;
TScreenBuf sb = (TScreenBuf) 0xa000;



И ещё: прочитал в книжке Павловской, как присвоить указателю адрес памяти в явном виде. char *vp = (char *)0xB8000000 Набираю пример. Дословно. Выдаётся ошибка: cannot cast from 'unsigned long' to 'char *'. В чём косяк?

Попробуй char far *

Romeo
19.10.2004, 11:48
char far *vp = (char far *)0xB8000000;

Всё прекрасно работает.