реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> указатель на тип void, попытки создать общую функцию
andrvisht
сообщение Jan 4 2006, 07:51
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(IgorKossak @ Jan 4 2006, 11:36) *
Наверное, всё-таки, не по времени выполнения, а по объёму, да и то при полном отсутствии оптимизации.

возможно, я думал что она оптимизирована изначально, кроме того я сравнивал для варианта преобразования числа (перевода его в строку LCD)
Цитата
Почему-то никто не говорит (или я пропустил), что void* надо приводить не только к char*, но и к __flash char*. На это и указывает сообщение компилятора о незавершенном типе.

c этого момента пожалуйста поподробнее...
Цитата
Основная ошибка в том, что в функции на момент исполнения нет информации о том, какого типа указатель был приведен к void*.

но у меня ошибка была на этапе компиляции самой функции, а не в точке её вызова. Или это как-то взаимосвязвно ?
Цитата
Решения было три:
- тип __generic;
- информация о типе указателя как аргумент в функции;
- два указателя.

хотел применить 2-е но в результате остановился на 1-м.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Jan 4 2006, 08:28
Сообщение #17


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(&-rey @ Jan 4 2006, 09:51) *
Цитата(IgorKossak @ Jan 4 2006, 11:36) *

Наверное, всё-таки, не по времени выполнения, а по объёму, да и то при полном отсутствии оптимизации.

возможно, я думал что она оптимизирована изначально, кроме того я сравнивал для варианта преобразования числа (перевода его в строку LCD)

??? Вообще-то Вы сами это либо задаёте либо нет в настройках проекта.
Цитата(&-rey @ Jan 4 2006, 09:51) *
Цитата

Почему-то никто не говорит (или я пропустил), что void* надо приводить не только к char*, но и к __flash char*. На это и указывает сообщение компилятора о незавершенном типе.

c этого момента пожалуйста поподробнее...
Цитата
Основная ошибка в том, что в функции на момент исполнения нет информации о том, какого типа указатель был приведен к void*.

но у меня ошибка была на этапе компиляции самой функции, а не в точке её вызова. Или это как-то взаимосвязвно ?

Ошибка у Вас стилистическая. А то, о чем сообщает компилятор, об этом Вам уже говорили. Повторюсь.
Вы писали
Цитата
(char*)pStr++;
Это означает, что pStr постоянно хранится в памяти или в регистрах в изначальном виде (типе). Временно приводится к типу char*, изымается по нему значение, он инкрементируется (если ещё инкрементируется), а в каком виде его теперь хранить (какого он типа?)?
В таком случае и нужен промежуточный указатель (не факт, что в результате он будет не тем же самым), который инициализируется единожды
Цитата
char*spStr = (char*)pStr;
и в дальнейшем только он и используется.
Цитата(&-rey @ Jan 4 2006, 09:51) *
Цитата

Решения было три:
- тип __generic;
- информация о типе указателя как аргумент в функции;
- два указателя.

хотел применить 2-е но в результате остановился на 1-м.

Насколько я помню тип __generic подразумевает также возможность указывания на __eeprom. Но даже и без этого Ваш код будет неприятно больше и работать будет заметно медленнее.
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 4 2006, 09:36
Сообщение #18


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(IgorKossak @ Jan 4 2006, 12:28) *
??? Вообще-то Вы сами это либо задаёте либо нет в настройках проекта.

Да конечно, возможно я не так выразился. Я имел предположение что поскольку функция библиотечная то она уже написана оптимально, а оптимизация в свойствах проекта влиять будет только на мой код. В принципе это можно проверить. так и сделаю.
Цитата
Ошибка у Вас стилистическая. А то, о чем сообщает компилятор, об этом Вам уже говорили......

да это я уже понял.
Цитата
Насколько я помню тип __generic подразумевает также возможность указывания на __eeprom. Но даже и без этого Ваш код будет неприятно больше и работать будет заметно медленнее.

ясно, это тоже проверю.
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Jan 5 2006, 07:38
Сообщение #19


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата
В принципе это можно проверить. так и сделаю.

Привожу данные после исследования скорости выполнения и размера *.bin файла (всего проекта) для 4 MHz m128.
сравнил вывод числа 65535 в массив при помощи sprintf(LCD,"%hu", 0xffff); (Normal DLIB)
и при помощи FloatToLCD(0,0,65535.0,0,1);
sprintf
без опт. разм. 6442 байт и 62008.5us с макс опт. разм. 6436 байт и 62008.25us
без опт. скор. 6442 байт и 62008.5us с макс опт. скор. 6436 байт и 62008.25us
FloatToLCD
без опт. разм. 2220 байт и 2315us с макс опт. разм. 2072 байт и 2287.75us
без опт. скор. 2252 байт и 2303us с макс опт. скор. 2116 байт и 2262.75us
Цитата
ясно, это тоже проверю.

Вариант с одним указателем типа __generic для вычитки из SRAM
без опт. разм. 2345 байт и 117.75us с макс опт. разм. 2073 байт и 92us
без опт. скорости 2351 байт и 96.5us с макс опт. скор. 2059 байт и 71.5us

Вариант с одним указателем типа __generic для вычитки из FLASH
без опт. разм. 2348 байт и 120.75us с макс опт. разм. 2080 байт и 94.75us
без опт. скор. 2354 байт и 99.5us с макс опт. скор. 2060 байт и 74.25us

Вариант с двумя указателями для SRAM и FLASH и равенстве нулю FLASH.
без опт. разм. 2353 байт и 115us с макс опт. разм. 2067 байт и 115.75us
без опт. скор. 2373 байт и 92us с макс опт. скор. 2073 байт и 74.25us

Вариант с двумя указателями для SRAM и FLASH и равенстве нулю SRAM.
без опт. разм. 2354 байт и 125.5us с макс опт. разм. 2068 байт и 118.5us
без опт. скор. 2374 байт и 102.5us с макс опт. скор. 2074 байт и 82.5us

Комментировать не буду, дабы не быть уличенным в пропаганде smile.gif
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 7 2006, 13:30
Сообщение #20


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(prottoss @ Jan 3 2006, 17:38) *
Вы сами отвечаете на свой вопрос. В Си вы не сможете объеденить два разных указателя под одним пустым типом VOID. Компилятор просто не знает, как формировать инкремент для данного типа. Указатель на SRAM изменяется линейно, указатель на FLASH имеет немного отличный механизм инкремента. Во-первых это указатель содержит адрес не байта, как в SRAM мо, а слова, где младший бит адреса указывает на тип байта в слове (старший или младший).


Вот это хит! ;>

Дело в том, что если взять адрес слова, и сдвинуть его на 1 влево, а освободившийся младший бит использовать для адресации байта (старшего и младшего), то получится линейный указатель, точно такой же как тот, что адресует (по вашим словам) SRAM. И действительно физически это одна и та же регистровая пара Z.
Go to the top of the page
 
+Quote Post
Old1
сообщение Jan 7 2006, 20:51
Сообщение #21


Знающий
****

Группа: Свой
Сообщений: 697
Регистрация: 26-07-05
Из: Могилев
Пользователь №: 7 095



To &-rey.
Я тут для себя тоже провел кое-какие эксперименты по созданию универсальной функции чтения строк. В соответствии с предложенными выше IgorKossak вариантами решения написал три функции, каждая из которых читает сроку из SRAM/FLASH/EEPROM и записывает ее в SRAM (если интересно файлы проекта прилагаются). И для себя сделал вывод, что более подходящий второй вариант (информация о типе указателя как аргумент в функции) (в моем случае Funk1(…)). Во-первых, в моем случае он работает быстрее чем остальные варианты (за исключением чтения из флэш, тут немного быстрее функция с __generic). Во-вторых, этот вариант более универсальный в плане переносимости на другой компилятор (ИМХО квалификатор __generic поддерживается только ИАР-ом), и в плане доступа к различным типам памяти: как я понял __generic не работает с ЕЕПРОМ. Есть конечно и недостатки: второй вариант решения занимает несколько больше места в памяти программ (по сравнению с __generic) но с этим ИМХО можно мириться. Конечно результаты достаточно относительны и зависят от реализации. На всякий случай привожу результаты тестирования .
Информация о типе указателя как аргумент в функции ( функция Funk1):
чтение из SRAM – (макс. оптимиз. по р-ру) 345 цикл., (макс. оптимиз. по скорости)340цикл.
чтение из FLASH – (макс. оптимиз. по р-ру) 428 цикл., (макс. оптимиз. по скорости)426цикл.
чтение из EEPROM – (макс. оптимиз. по р-ру) 937 цикл., (макс. оптимиз. по скорости)938цикл.
Объем кода, макс. опт.по разм./ макс. опт. по скор. – 70/70

Использование квалификатора __generic (функцияFunk2):
чтение из SRAM – (макс. оптимиз. по р-ру) 387 цикл., (макс. оптимиз. по скорости)387цикл.
чтение из FLASH – (макс. оптимиз. по р-ру) 417 цикл., (макс. оптимиз. по скорости)417цикл.
чтение из EEPROM –не работает.
Объем кода, макс. опт.по разм./ макс. опт. по скор. – 44/44

Три указателя (функция Funk3):
чтение из SRAM – (макс. оптимиз. по р-ру) 389 цикл., (макс. оптимиз. по скорости)363цикл.
чтение из FLASH – (макс. оптимиз. по р-ру) 509 цикл., (макс. оптимиз. по скорости)481цикл.
чтение из EEPROM – (макс. оптимиз. по р-ру) 1085 цикл., (макс. оптимиз. по скорости)1057цикл.
Объем кода, макс. опт.по разм./ макс. опт. по скор. – 86/94
Прикрепленные файлы
Прикрепленный файл  Uni_Read_String.rar ( 1.62 килобайт ) Кол-во скачиваний: 54
 
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 7 2006, 21:17
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(defunct @ Jan 7 2006, 20:30) *
Цитата(prottoss @ Jan 3 2006, 17:38) *

Вы сами отвечаете на свой вопрос. В Си вы не сможете объеденить два разных указателя под одним пустым типом VOID. Компилятор просто не знает, как формировать инкремент для данного типа. Указатель на SRAM изменяется линейно, указатель на FLASH имеет немного отличный механизм инкремента. Во-первых это указатель содержит адрес не байта, как в SRAM мо, а слова, где младший бит адреса указывает на тип байта в слове (старший или младший).


Вот это хит! ;>

Дело в том, что если взять адрес слова, и сдвинуть его на 1 влево, а освободившийся младший бит использовать для адресации байта (старшего и младшего), то получится линейный указатель, точно такой же как тот, что адресует (по вашим словам) SRAM. И действительно физически это одна и та же регистровая пара Z.


Хит это или нет, но я и имел ввиду, что компилятор не знает, сдвигать указатель на бит или нет. Читайте внимательнее топики (или купите монитор многодюймовый)


--------------------
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 9 2006, 15:36
Сообщение #23


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(prottoss @ Jan 7 2006, 23:17) *
Цитата(defunct @ Jan 7 2006, 20:30) *
Цитата(prottoss @ Jan 3 2006, 17:38) *

Вы сами отвечаете на свой вопрос. В Си вы не сможете объеденить два разных указателя под одним пустым типом VOID. Компилятор просто не знает, как формировать инкремент для данного типа. Указатель на SRAM изменяется линейно, указатель на FLASH имеет немного отличный механизм инкремента. Во-первых это указатель содержит адрес не байта, как в SRAM мо, а слова, где младший бит адреса указывает на тип байта в слове (старший или младший).


Вот это хит! ;>

Дело в том, что если взять адрес слова, и сдвинуть его на 1 влево, а освободившийся младший бит использовать для адресации байта (старшего и младшего), то получится линейный указатель, точно такой же как тот, что адресует (по вашим словам) SRAM. И действительно физически это одна и та же регистровая пара Z.


Хит это или нет, но я и имел ввиду, что компилятор не знает, сдвигать указатель на бит или нет. Читайте внимательнее топики (или купите монитор многодюймовый)


"Не говорите мне что делать, и я не скажу Вам куда идти" © begin...end. smile.gif

В Вашей цитате не было написано того, о чем Вы сейчас говорите. Чтобы сказанное Вами было понятно не только Вам, а всем, я бы добавил, что указатели на Flash могут быть двух типов:
1. указатель на функцию - тогда флеш указатель указывает на СЛОВО (сдвинут на 1 вправо);
2. указатель на данные - тогда флеш указатель указывает на БАЙТ (линейный указатель как и при адресации SRAM).

Согласитесь, что "указатель содержит адрес не байта, как в SRAM мо, а слова, где младший бит адреса указывает на тип байта в слове (старший или младший)" - фраза не совсем понятная и не раскрывает сути вопроса.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 9 2006, 19:29
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(defunct @ Jan 9 2006, 22:36) *
"Не говорите мне что делать, и я не скажу Вам куда идти" © begin...end. smile.gif

В Вашей цитате не было написано того, о чем Вы сейчас говорите. Чтобы сказанное Вами было понятно не только Вам, а всем, я бы добавил, что указатели на Flash могут быть двух типов:
1. указатель на функцию - тогда флеш указатель указывает на СЛОВО (сдвинут на 1 вправо);
2. указатель на данные - тогда флеш указатель указывает на БАЙТ (линейный указатель как и при адресации SRAM).

Согласитесь, что "указатель содержит адрес не байта, как в SRAM мо, а слова, где младший бит адреса указывает на тип байта в слове (старший или младший)" - фраза не совсем понятная и не раскрывает сути вопроса.




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

Сообщение отредактировал prottoss - Jan 9 2006, 19:56


--------------------
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 9 2006, 20:01
Сообщение #25


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(prottoss @ Jan 9 2006, 21:29) *
а Вы вместо того чтобы это же умно и доходчиво, что б всем понятно было, даже коровам, сразу объснить, флудить начали.


Извините, в этом я был действительно неправ.
Go to the top of the page
 
+Quote Post
ObitJr
сообщение Jan 10 2006, 19:17
Сообщение #26


Участник
*

Группа: Участник
Сообщений: 16
Регистрация: 23-07-05
Пользователь №: 7 043



Я думаю неправильно говорить компилятор незнает или неумеет. По стандарту "C" обязан делать инкремент УКАЗАТЕЛЮ типа void и при этом безразлично как в конечном итоге интерпретируется адрес. Дело в том что архитектура AVR непозволяет этого сделать. Доступ, насколько я помню, к FLASH области и SRAM области совсем разные...
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 10 2006, 19:57
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(ObitJr @ Jan 11 2006, 02:17) *
Я думаю неправильно говорить компилятор незнает или неумеет. По стандарту "C" обязан делать инкремент УКАЗАТЕЛЮ типа void и при этом безразлично как в конечном итоге интерпретируется адрес. Дело в том что архитектура AVR непозволяет этого сделать. Доступ, насколько я помню, к FLASH области и SRAM области совсем разные...


А мне как раз кажется наоборот. И что серьезно "...По стандарту "C" обязан делать инкремент УКАЗАТЕЛЮ типа void и при этом безразлично как в конечном итоге интерпретируется адрес...". А как тогда, к примеру, Вы прокомментируете вот такой код:

Код
  

/* объявление структур */

typedef struct Struct1_type{

int a,b,c,d,e,f;

} Struct1;

typedef struct Struct2_type{

char a,b,c,d,e,f;

} Struct2;

/* объявление функций  и переменных*/

Struct1 Struct1_Array[10];

Struct2 Struct2_Array[10];

void MySuperFunc(void* ptr){

ptr++;

}

/* Где то в программе */

......

MySuperFunc(&Struct1_Array[0]);

......

MySuperFunc(&Struct2_Array[0]);

.....


Интересно, как MySuperFunc узнает, с каким типом данных ей работать? Размер одного типа данных отличается от другого в два раза. Прочитает исходник? Ей же кроме адреса массива ничего больше не передается! Вот если бы мы кроме указателя передавали еще одним параметром в функцию ее тип, то функция могла бы определить , с чем ей работать. Допустим примерно так:

Код
  

#define TYPE_STRUCT1 0

#define TYPE_STRUCT2 1

...

void MySuperFunc(void* ptr, char type){

if(type == TYPE_STRUCT1){

(Struct1*)ptr++;

}

if(type == TYPE_STRUCT2){

(Struct2*)ptr++;

}

}

/* Где то в программе */

......

MySuperFunc(&Struct1_Array[0], TYPE_STRUCT1);

......

MySuperFunc(&Struct2_Array[0], TYPE_STRUCT2);

.....


--------------------
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Jan 10 2006, 20:27
Сообщение #28


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



указатель void, ИМХО, действительно не может знать величину приращения при любыхарифметических действиях с ним.
void MySuperFunc(void* ptr, char type){
Struct1* ptr1 = ptr;
Struct2* ptr2 = ptr;
if(type == TYPE_STRUCT1) ptr1++;
if(type == TYPE_STRUCT2) ptr2++;
}


--------------------
aka Vit
Go to the top of the page
 
+Quote Post
ObitJr
сообщение Jan 10 2006, 21:33
Сообщение #29


Участник
*

Группа: Участник
Сообщений: 16
Регистрация: 23-07-05
Пользователь №: 7 043



1. Если что-то кажется, я конечно извеняюсь, есть единственный выход - берем стандарт к примеру 99й и смотрим.
2. Можно приводить примеры работы со структурами, пайпами и.т.д, но ни я никто другой ничего об этом не говорил, а говорили об адресации.
3. Также, я не говорил что через указатель на void можно перескакивать через несколько байт, слов или элементов структур (применительно к их расположению в памяти) (хотя по стандарту для некоторых архитектур возможно), а адресация к ячейкам памяти - пожайлуста.
4. В этом топике обсуждались функции вывода СТРОК только из двух источников, а не чего-либо из структур (можно и строку расположить по три символа в разных частях SRAM - тогда все приведенные функции будут неверны).
5. К 1 вдогонку - попробуйте на любых других архитектурах (x86, PowerPC тотже ARM) сделать инкремент УКАЗАТЕЛЯ на void - и все ОК, для 86й на куче компиляторов, на PPC и ARM тоже все нормально (правда только под gcc пробовал).

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

То что я говорил, не меняет того факта, что сделать нормальную универсальную функцию нельзя, но всетаки... смысл то имеет разобраться в стандартах и как в таких случаях поступает компилятор...
Go to the top of the page
 
+Quote Post
dxp
сообщение Jan 11 2006, 07:19
Сообщение #30


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(ObitJr @ Jan 11 2006, 03:33) *
1. Если что-то кажется, я конечно извеняюсь, есть единственный выход - берем стандарт к примеру 99й и смотрим.
...
То что я говорил, не меняет того факта, что сделать нормальную универсальную функцию нельзя, но всетаки... смысл то имеет разобраться в стандартах и как в таких случаях поступает компилятор...

Что-то все равно не понятно. Отсылания к Стандартам, к сожалению, не проясняют ситуацию. Если уж ссылаетесь на Стандарт, то указывайте конкретный номер параграфа и пункта. А еще лучше прямо цитату сюда.

Я проще спрошу, хотя и тоже на примере (чтобы понятнее было). Вот имеем функцию:
Код
void f(void* p)
{
    *p++ = 10;
    *p++ = 20;
}


Условия следующие: пусть аппаратная платформа AVR программная EWAVR - все это означает, что

sizeof(char) == 1
sizeof(int) == 2
sizeof(long) == 4
sizeof(float) == 4
sizeof(void*) == 2
и т.д.

Теперь пусть имеем, скажем, массив

char A[64];

расположенный по адресу 0x100, и передаем его адрес в функцию:
...
f((void*)A);
...

Вопрос: по какому адресу запишется число 20 (если этот код вообще скомпилируется, в чем есть большие сомнения smile.gif)? И как эту ситуацию описывает Стандарт - с ссылкой на конкретный пункт, пожалуйста.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 17th June 2025 - 13:25
Рейтинг@Mail.ru


Страница сгенерированна за 0.01658 секунд с 7
ELECTRONIX ©2004-2016