void pointer
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
void pointer
как правильно создать void pointer in C:
void *ptr;
или
void* ptr;
Вижу и так и так пишуть. Или ето одно и тоже? совсем запутался...
void *ptr;
или
void* ptr;
Вижу и так и так пишуть. Или ето одно и тоже? совсем запутался...
All rights reserved, all wrongs revenged.
-
- Уже с Приветом
- Posts: 15770
- Joined: 01 Mar 2008 15:14
Re: void pointer
и так и так правильно
-
- Уже с Приветом
- Posts: 2001
- Joined: 10 Nov 2004 00:34
- Location: MD
Re: void pointer
Это одно и то же. Пробелы в C влияют только на разделение токенов, ну и в строках, конечно.
Можно даже написать:
Первый вариант лучше тем, что тип отделён от имени переменной.
Второй вариант лучше в случае объявления нескольких переменных, т.к. звёздочка относится таки к идентификатору, а не void.
Например в коде:ptr1 - указатель, а ptr2 - нет.
Дабы не смущать человеческий парсер лучше писать:или вообще не объявлять несколько указателей в одной строке.
Можно даже написать:
Code: Select all
void
*
ptr
;
Второй вариант лучше в случае объявления нескольких переменных, т.к. звёздочка относится таки к идентификатору, а не void.
Например в коде:
Code: Select all
int* ptr1, ptr2;
Дабы не смущать человеческий парсер лучше писать:
Code: Select all
int *ptr1, *ptr2;
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
Re: void pointer
ок, спасибо. Правильно ли я понимаю что две строки ниже тоже одно и тоже:
и здесь
Code: Select all
int CmpFunc(const void* _a, const void* _b) { ...}
int CmpFunc(const void *_a, const void *_b) { ...}
Code: Select all
const float* a = (const float*) _a;
const float *a = (const float *) _a;
All rights reserved, all wrongs revenged.
-
- Уже с Приветом
- Posts: 15770
- Joined: 01 Mar 2008 15:14
Re: void pointer
Секундочку.. Вообще-то ведь нельзя указатель на Void создать. Как можно создать указатель на участок памяти размерностью 0
-
- Уже с Приветом
- Posts: 28294
- Joined: 29 Aug 2000 09:01
- Location: SPB --> Gloucester, MA, US --> SPB --> Paris
Re: void pointer
Эх, молодежь...OtherSide wrote:Секундочку.. Вообще-то ведь нельзя указатель на Void создать. Как можно создать указатель на участок памяти размерностью 0
Зарегистрированный нацпредатель, удостоверение N 19719876044787 от 22.09.2014
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
Re: void pointer
размерность будет не ноль а такая, на которую указывает void pointer.OtherSide wrote:Секундочку.. Вообще-то ведь нельзя указатель на Void создать. Как можно создать указатель на участок памяти размерностью 0
All rights reserved, all wrongs revenged.
-
- Уже с Приветом
- Posts: 15770
- Joined: 01 Mar 2008 15:14
Re: void pointer
И то правда, у меня уже мозги от собеседований едут. Недавно спрашивали, что будет если сделать (void*)++
-
- Уже с Приветом
- Posts: 3000
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: void pointer
А в чем проблема? Указатель типа `void *` указывает на безразмерную точку в памяти. `void` является неполным типом, и у него нет размера. Поэтому разадресовать `void *` указатель нельзя и применять адресную арифметику к `void *` указателю нельзя. А вот сранивать такие указатели (в рамках общих органичений) можно. Ну и, понятное дело, приводить их к другим указательным типам можно.OtherSide wrote:Секундочку.. Вообще-то ведь нельзя указатель на Void создать. Как можно создать указатель на участок памяти размерностью 0
В языке С оператор `++` к указателю типа `void *`не применим. Но вопрошающие могут быть испрочены GNU-расширениями, в которых разрешается применять адресную арифметику к `void *`. Последний при этом ведет себя как `char *`.OtherSide wrote:Недавно спрашивали, что будет если сделать (void*)++
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
Re: void pointer
Вы про какой язык? Если про C, то void pointer означает что pointer может указывать на любой тип данных. Размер етих данных вполне определенный:AndreyT wrote:А в чем проблема? Указатель типа `void *` указывает на безразмерную точку в памяти.OtherSide wrote:Секундочку.. Вообще-то ведь нельзя указатель на Void создать. Как можно создать указатель на участок памяти размерностью 0
Code: Select all
void *ptr; // ptr is declared as Void pointer
char cnum;
int inum;
float fnum;
ptr = &cnum; // ptr has address of character data
ptr = &inum; // ptr has address of integer data
ptr = &fnum; // ptr has address of float data
All rights reserved, all wrongs revenged.
-
- Уже с Приветом
- Posts: 3000
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: void pointer
Я вам про Фому, а вы мне про Ерему.thinker wrote:Вы про какой язык? Если про C, то void pointer означает что pointer может указывать на любой тип данных. Размер етих данных вполне определенный:AndreyT wrote:А в чем проблема? Указатель типа `void *` указывает на безразмерную точку в памяти.OtherSide wrote:Секундочку.. Вообще-то ведь нельзя указатель на Void создать. Как можно создать указатель на участок памяти размерностью 0
Язык С - это язык со статической типизацией. С точки зрения языка `void *` указывает на неполный тип `void`. Это некое абстарктной положение - точка - в памяти и не более. Это все что интересно языку.
А то, что вы там лично знаете, что на самом деле в этом месте хранится какой-то объект типа `float` - это языку С не интересно. Никаких фич, основанных на этом факте, в языке С нет и быть не может. Если вы лично знаете, что ваш `void *` указывает на какой-то объект типа `float`, то доступиться к этому объекту типа `float` вы сможете только после приведения `void *` к типу `float *`. Но с этого момента вы уже не работатете с `void *`, а работаете с `float *`.
С таким же успехом вы можете использовать указатель `int *` для того, чтобы указывать на объект типа `float`. Преобразуйте типы указателей - и готово. Язык вам этого не запрещает. Вы-то при этом будуте знать, что указатель `int *` фактически указывает на `float`, но языку до этого никакого дела нет. Язык будет считать, что `int *` указывает на `int` со всеми вытекающими.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
Re: void pointer
Это интересно прежде всего мне, а не языку. Язык - это инструмент, как например, рубанок для плотника. Что можно быть интересно рубанку???AndreyT wrote:Язык С - это язык со статической типизацией. С точки зрения языка `void *` указывает на неполный тип `void`. Это некое абстарктной положение - точка - в памяти и не более. Это все что интересно языку.
После ptr = &fnum;
мы имеем не абстракную точку в памяти, а вполне конкретный (физический) адрес, где храниться перенная fnum и тип етой переменной float. Именно этот адрес меня и интересует чтобы в какой-то момент изменить значение данной переменной по данному адресу.
All rights reserved, all wrongs revenged.
-
- Уже с Приветом
- Posts: 3000
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: void pointer
Темой обсуждения пока что являлся указатель типа `void *`. Никакого доступа ни к какой переменой типа `float` указатель типа `void *` вам предоставить не может. Доступ к переменной типа `float` может предоставить только указатель типа `float *`. Интересно это вам или не интересно - вопрос посторонний.thinker wrote:мы имеем не абстракную точку в памяти, а вполне конкретный (физический) адрес, где храниться перенная fnum и тип етой переменной float. Именно этот адрес меня и интересует
чтобы в какой-то момент изменить значение данной переменной по данному адресу.
А рассуждения типа "из указателя типа `void *` я могу получить указатель типа `float *`, а это значит, что доступ к переменной типа `float` предоставлен именно указателем типа `void *`" - это примерно то же самое, что заявлять, что доступ к переменным типа `float` мне сегодня предоставил велосипед, так как я на нем на работу приехал.
P.S. "Конкретный (физический) адрес" - это то же самое, что "абстракная точка в памяти". Словом "абстрактная" я лишь подчеркиваю нетипизированность указателя `void *`, не более.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
Re: void pointer
OK, в каком месте вышеуказанного кода мы приводим `void *` к типу `float *` ?AndreyT wrote:Если вы лично знаете, что ваш `void *` указывает на какой-то объект типа `float`, то доступиться к этому объекту типа `float` вы сможете только после приведения `void *` к типу `float *`.
All rights reserved, all wrongs revenged.
-
- Уже с Приветом
- Posts: 3000
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: void pointer
Сказано же "доступиться к этому объекту типа `float` вы сможете только после приведения `void *` к типу `float *`". Ключевое слово - доступиться. В вашем вышеуказанном коде никаких попыток доступится к объекту типа `float` нет и в помине. В тексте вы у себя упоминаете доступ (цитирую: "...чтобы в какой-то момент изменить значение данной переменной по данному адресу..."), а в коде - ни разу даже и не пытались. Поэтому и приведения в вашем коде нет.thinker wrote:OK, в каком месте вышеуказанного кода мы приводим `void *` к типу `float *` ?AndreyT wrote:Если вы лично знаете, что ваш `void *` указывает на какой-то объект типа `float`, то доступиться к этому объекту типа `float` вы сможете только после приведения `void *` к типу `float *`.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 3000
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: void pointer
AndreyT wrote:Сказано же "доступиться к этому объекту типа `float` вы сможете только после приведения `void *` к типу `float *`". Ключевое слово - доступиться. В вашем вышеуказанном коде никаких попыток доступится к объекту типа `float` нет и в помине. В тексте вы у себя упоминаете доступ (цитирую: "...чтобы в какой-то момент изменить значение данной переменной по данному адресу..."), а в коде - ни разу даже и не пытались. Поэтому и приведения нет.thinker wrote:OK, в каком месте вышеуказанного кода мы приводим `void *` к типу `float *` ?AndreyT wrote:Если вы лично знаете, что ваш `void *` указывает на какой-то объект типа `float`, то доступиться к этому объекту типа `float` вы сможете только после приведения `void *` к типу `float *`.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
Re: void pointer
То есть вы считаете, что поинтер в вышеуказанном коде не будет работать правильно? Тогда приведите как это исправить так чтобы мы могли обращаться к переменной fnum через поинтер void *ptr.
All rights reserved, all wrongs revenged.
-
- Уже с Приветом
- Posts: 3000
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: void pointer
Мы, очевидно, друг друга не понимаем. Все будет правильно работать. Только для того, чтобы, например, прочитать значение вашей переменнойthinker wrote:То есть вы считаете, что поинтер в вышеуказанном коде не будет работать правильно? Тогда приведите как это исправить так чтобы мы могли обращаться к переменной fnum через поинтер void *ptr.
Code: Select all
float fnum = 42;
Code: Select all
void *ptr = &fnum;
Code: Select all
float value = *(float *) ptr;
Всякий раз, когда вы захотите доступиться к вашей `float` переменной через `ptr`, по чтению ли, по записи ли, вам волей-неволей придется выполнять преобразование типа к `float *`.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
-
- Уже с Приветом
- Posts: 15276
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: void pointer
например, так:OtherSide wrote:Секундочку.. Вообще-то ведь нельзя указатель на Void создать. Как можно создать указатель на участок памяти размерностью 0
Code: Select all
void* ass = (void *) "жопа";
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 15276
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: void pointer
размерности как таковой может не бытьthinker wrote:размерность будет не ноль а такая, на которую указывает void pointer.OtherSide wrote:Секундочку.. Вообще-то ведь нельзя указатель на Void создать. Как можно создать указатель на участок памяти размерностью 0
дорожный знак "до чикаго 123 мили" ничего не говорит о протяженности чикаго.
впрочем, АндрейТ как всегда все качественно абиснил
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 26871
- Joined: 29 Aug 2000 09:01
Re: void pointer
Кстати при передачи void pointer'a в другую функцию, например:AndreyT wrote:Т.е. вам придется выполнить преобразование типа от `void *` к `float *`. Результат этого преобразования типа - это уже новый самостоятельный временный указатель типа `float *`.
Code: Select all
void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
...
...
qsort( array, 10 , sizeof( int ), int_sorter );
All rights reserved, all wrongs revenged.
-
- Уже с Приветом
- Posts: 3000
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: void pointer
А функция `qsort`, как таковая, и не хочет его знать. Внутри функции `qsort` работа ведется в терминах байтов, поэтому сама функция `qsort` будет приводить все указатели к типу `char *` и выполнять адресную арифметику в терминах типа `char *`. Всё, что `qsort` хочет дополнительно знать про ваши данные, это их количество - параметр `nmemb` - и размер индивидуального элемента в байтах - параметр `size`. Эти размеры будут использоваться `qsort` для выполнения адресной арифметики над `(char *) base`. Т.е. `(char *) base + i * size` даёт указатель на положение в памяти i-того элемента вашего массива. Это всё, что нужно самой `qsort`.thinker wrote:Кстати при передачи void pointer'a в другую функцию, например:где происходит преобразование такого поинтера в конкретный тип данных? Меня интересует поинтер void *base. Ведь при передаче массива "array" функция qsort не знает тип переданных ей данных.Code: Select all
void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); ... ... qsort( array, 10 , sizeof( int ), int_sorter );
К вашим конкретным данным реализация функции `qsort` сама по себе никогда не доступается - сами данные голому алгоритму `qsort` глубоко безразличны. И конкретный тип ваших данных функции `qsort` тоже глубоко безразличен. Функцию `qsort` интересует только положение элементов вашего массива (см. выше) и результат сравнения элементов вашего массива. А сравнение будет выполнять отнюдь не сам `qsort`. Сравнение будете выполнять вы сами. Вы сами предоставляете `qsort` вашу собственную callback-функцию `int_sorter` для сравнения элементов вашего массива. Вы сами, разумеется, знаете, что ваш массив содержит элементы типа `int`. Поэтому внутри вашей `int_sorter` вы сами будете приводить переданные вам из `qsort` указатели типа `const void *` к типу `const int *` и выполнять сравнение. Например, для сортировки целых чисел по возрастанию
Code: Select all
int int_sorter(const void *p1, const void *p2)
{
const int *i1 = p1, *i2 = p2;
return (*i1 > *i2) - (*i1 < *i2);
}
Этот callback-компаратор - это единственное место во всей процедуре сортировки, которое работает с вашим конктерным типом `int`. Самой же общей реализации `qsort`, как я уже говорил выше, до вашего конкретного типа данных никакого дела нет. `qsort` хочет знать лишь размер ваших данных и вы этот размер туда сами передаете.
Best regards,
Андрей
Андрей
-
- Уже с Приветом
- Posts: 3000
- Joined: 14 Apr 2004 01:11
- Location: SFBA (было: Минск, Беларусь)
Re: void pointer
AndreyT wrote:А функция `qsort`, как таковая, и не хочет его знать. Внутри функции `qsort` работа ведется в терминах байтов, поэтому сама функция `qsort` будет приводить все указатели к типу `char *` и выполнять адресную арифметику в терминах типа `char *`. Всё, что `qsort` хочет дополнительно знать про ваши данные, это их количество - параметр `nmemb` - и размер индивидуального элемента в байтах - параметр `size`. Эти размеры будут использоваться `qsort` для выполнения адресной арифметики над `(char *) base`. Т.е. `(char *) base + i * size` даёт указатель на i-тый элемент вашего массива. Это всё что нужно самой `qsort`.thinker wrote:Кстати при передачи void pointer'a в другую функцию, например:где происходит преобразование такого поинтера в конкретный тип данных? Меня интересует поинтер void *base. Ведь при передаче массива "array" функция qsort не знает тип переданных ей данных.Code: Select all
void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); ... ... qsort( array, 10 , sizeof( int ), int_sorter );
К вашим конкретным данным реализация функции `qsort` сама по себе никогда не доступается - сами данные голому алгоритму `qsort` глубоко безразличны. И конкретный тип ваших данных функции `qsort` тоже глубоко безразличен. Функцию `qsort` интересует только результат сравнения элементов вашего массива. А сравнение будет выполнять отнюдь не сам `qsort`. Сравнение будете выполнять вы сами. Вы сами предоставляете `qsort` вашу собственную callback-функцию `int_sorter` для сравнения элементов вашего массива. Вы сами, разумеется, знаете, что ваш массив содержит элементы типа `int`. Поэтому внутри вашей `int_sorter` вы сами будете приводить переданные вам из `qsort` указатели типа `const void *` к типу `const int *` и выполнять сравнение. Например, для сортировки целых чисел по возрастанию
Вот оно, то самое приведение типа, о котором вы спрашивали. Еще раз, заметьте, что приведение типа расположено в вашем коде, а не в коде `qsort`.Code: Select all
int int_sorter(const void *p1, const void *p2) { const int *i1 = p1, *i2 = p2; return (*i1 > *i2) - (*i1 < *i2); }
Этот callback-компаратор - это единственное место во всей процедуре сортировки, которое работает с вашим конктерным типом `int`. Самой же общей реализации `qsort`, как я уже говорил выше, до вашего конкретного типа данных никакого дела нет. `qsort` хочет знать лишь размер ваших данных и вы этот размер туда сами передаете.
Best regards,
Андрей
Андрей