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

 
 
> Вопрос С
badik
сообщение Jun 24 2010, 18:29
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 29-11-06
Из: Екатеринбург
Пользователь №: 22 890



Здравствуйте, Вопрос к людям хорошо знающим С.
Понадобилась функция перевода целого числа в строку. Перерыл спрвочник и help - результат 0.
Банальная проблема. Увы. Обраных функций вагон.
Go to the top of the page
 
+Quote Post
8 страниц V  « < 3 4 5 6 7 > »   
Start new topic
Ответов (60 - 74)
ViKo
сообщение Jun 28 2010, 21:09
Сообщение #61


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Прежде, чем писать новое, изучил в отладчике работу обеих моих программ - начальной si16toad и измененной itoa, в которой операции % и / были заменены вызовом библиотечной функции div. Напомню: Keil uVision - RealView MDK-ARM 4.10, STM32F103. Результаты оказались интересными.

После компиляции в окне Build Ouitput для обеих программ выдаются одинаковые размеры для кода - 548 байтов при оптимизации O0 и 536 байтов при оптимизации O3. Почему они одинаковые, не понимаю (см. ниже)?! Размеры данных всех типов тоже одинаковые вообще всегда, но это, как раз, не удивляет.

Посчитал размер обеих функций по листингу C компилятора (есть галочка в настройках генерировать листинг). При O0 для si16toad насчитал 84 байта, для itoa 98 байтов (не считая 14 байтов в самой функции div, это уже в отладчике увидел). При O3 - 80 байтов и 94 байта, соответственно. Причем, при оптимизации O0 в si16toad команда деления использовалась дважды, а при O3 только один раз. В-общем, мой первый вариант оказался компактнее.

Посчитал в отладчике количество тактов. Счетчик тактов виден в окне регистров, засекал значение перед вызовом своей функции и после нее. При O0 si16toad выполнялась за 171 такт, itoa за 232 такта. При O3 - 121 такт и 210 тактов, соответственно. Мой первый вариант оказался еще и быстрее.

Увидел лишние знаковые и беззнаковые расширения для переменных меньше 32 байтов. Вот здесь буду совершенствовать программу. Массив или указатель - тоже проверю. Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю.


Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 28 2010, 21:33
Сообщение #62


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (ViKo @ Jun 29 2010, 00:09) *
Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю.

Их у Вас четыре. Можете попробовать на пальцах посчитать от X0 (раз-два) до X32768(раз-два-..шесть). Ну и размер должен быть на на уровне 60 байт, ну и тактов заметно менее.




--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 28 2010, 21:57
Сообщение #63


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 00:33) *
Их у Вас четыре. Можете попробовать на пальцах посчитать от X0 (раз-два) до X32768(раз-два-..шесть). Ну и размер должен быть на на уровне 60 байт, ну и тактов заметно менее.

Перед "0" я символ + или - не ставлю (считаю, так "красивее" и "правильнее"), потому и обработка такая в начале программ. Итого _ _ _ _ _ 0 \0.
По поводу размеров и тактов - могу выдать весь проект в заархивированном виде.
В настройках есть какие-то "галочки", которых не трогал. Может, что-то и упустил...
Прикрепленные файлы
Прикрепленный файл  Keil_Temp.zip ( 144.56 килобайт ) Кол-во скачиваний: 14
 
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 28 2010, 22:03
Сообщение #64


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (ViKo @ Jun 29 2010, 00:57) *
Перед "0" я символ + или - не ставлю

Вы ставите один из 3x символов. Вот и ставьте. Таки 4 smile.gif
QUOTE
По поводу размеров и тактов - могу выдать весь проект в заархивированном виде.

Я говорю об аккуратно написанном, посему про 80 байтов в Вашем варианте верю. Сделайте 60 smile.gif.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 08:29
Сообщение #65


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



2 zltigo
Непременно. smile.gif
Выставил две "галки" - Use Cross-Module Optimization и Use MicroLIB. Общий размер кода сократился до 212 и 324 байтов для первой и второй программ. Причем, такой размер получается со второго раза компиляции. "Все чудесатее и чудесатее." Что эти параметры делают? А на конкретный размер и состав кода пока не смотрел.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 13:48
Сообщение #66


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Код
void  itoad(int number, uint8_t *string)
{
  uint8_t  sign;
  *(int32_t *) string =       ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24;
  *(int32_t *)(string + 4) =  ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24;  
  *(int32_t *)(string += 8) = ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24;
  if (!number) return;
  if (number > 0) sign = '+';
  else {
    number = -number;
    sign = '-';
  }
  string += 2;
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}

Работает с 32-битовыми числами со знаком.
string должна быть 12 байтов для 32-битового числа.
60 байтов (+ 4 байта хранят константу "_ _ 0").
~207 тактов.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 29 2010, 14:18
Сообщение #67


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Jun 29 2010, 16:48) *
Код
*(int32_t *) string =
Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 14:29
Сообщение #68


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Jun 29 2010, 17:18) *
Знатная грабля

А для Cortex-M3? А как надо по вашему мнению?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 14:34
Сообщение #69


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (Сергей Борщ @ Jun 29 2010, 17:18) *
Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные.

Это гнулось под Cortex - такая вот игра.
QUOTE (ViKo @ Jun 29 2010, 16:48) *
60 байтов

Чуть симпатичнее и скорее всего еще короче:
CODE
void  itoad(int number, uint8_t *string)
{
  uint8_t  sign;
  *(uint32_t *) string =       '    ';
  *(uint32_t *)(string + 4) =  '    ';  
  *(uint32_t *)(string += 10) = (uint32_t )"  0";
  if (!number) return;
  if (number > 0) sign = '+';
  else {
    number = -number;
    sign = '-';
  }
//  string += 2;
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}

Осталось первоначальную 16bit оптимизировать.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 14:39
Сообщение #70


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 17:34) *
*(uint32_t *) string = ' ';
*(uint32_t *)(string + 4) = ' ';
Осталось первоначальную 16bit оптимизировать.

Кавычки не двойные?
Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 14:45
Сообщение #71


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (ViKo @ Jun 29 2010, 17:39) *
Кавычки не двойные?

В первых двух - нет. Возможны warnings, правда, поскольку символ wide получается ИЗ 4x ПРОБЕЛОВ. А так нормально. В третьей - три символа в двойных.
QUOTE
Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий.

Автоматически, не значит оптимально.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 17:23
Сообщение #72


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 17:34) *
Код
  *(uint32_t *)(string += 10) = (uint32_t )"  0";

Так - нельзя, пропускается два байта.
С кавычками - понял, но варнинги... как бы удовлетворить требованиям компилятора?
Код
#define  FOUR_SPACES  0x20202020
*(uint32_t *) string = FOUR_SPACES;

Нормально?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 17:40
Сообщение #73


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (ViKo @ Jun 29 2010, 20:23) *
Так - нельзя, пропускается два байта.

А, да. Что-то ошибся.
Тогда так:
CODE
  *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
  *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
  string += 2;

Есть шанс на экономию пары байт.

QUOTE
С кавычками - понятно, но варнинги... как бы удовлетворить требованиям компилятора?

Ну, например, отключить их локально прагмой, либо таки (long)" ", но константа займет 8 байт.



QUOTE (ViKo @ Jun 29 2010, 20:23) *
Нормально?

Да.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jun 29 2010, 18:29
Сообщение #74


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(zltigo @ Jun 29 2010, 20:40) *
Код
  *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
  *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
  string += 2;

Есть шанс на экономию пары байт.

В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель? А, заменить +8 +2 на +4 +4 +2?
upd. Попробовал и так, и сяк, и +10, лучше не становится.

16-битовую хочу попробовать с применением формата 4.28, как у aaarrr. А с тем, что сделал для 32 битов, и не знаю, куда уж дальше "копать" для 16 битов. Я, собственно, с 16-битовой и возился, пока не увидел, что 32-битовая из нее получается практически "даром":)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 29 2010, 18:38
Сообщение #75


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (ViKo @ Jun 29 2010, 21:29) *
В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель?

Вот как написано, так пробуйте.
QUOTE
что 32-битовая из нее получается практически "даром":)

Полагаю, что там есть как минимум один нюанс - не ухудшить шестнадцатибитовостью ну и чуть поджать за счет меньшего буфера.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th July 2025 - 09:31
Рейтинг@Mail.ru


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