Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

[uquote="Зурбаган",url="/forum/viewtopic.php?p=3129745#p3129745"]Да нет, тут не в практической реализации дело. Судя по вашему первому вопросу, уж извините, дело в теоретических пробелах.[/uquote]
Для меня реализация в программе - это именно практика. Смысл указателя, получение содержимого по указателю (*) и получение адреса переменной, на который он указывает (&), мне понятны.

Я же писал выше, что у меня получилось избавиться от ошибок.
После исправления у меня получилось так:

Код: Выделить всё

void lcd_out (unsigned char row, unsigned char col, unsigned char *text)
{
  unsigned char ch, i;
  
  lcd_setxy(row,col*6);
  while (*text)
  {
    ch = *text;
    if ((ch >= 32) && (ch <= '~')) ch -= 32;
      else if ((ch >= 192) && (ch <= 255)) ch -= 97; // 'А' <= ch <= 'я'
        else ch = 255;
    for (i = 0; i < 5 ; i++)
    {
      lcd_send(*(lcd_font[0]+ch * 5 + i),DTA);
    }
    lcd_send(0,DTA);  // Additional space
    text++;
  }
}
Я изначально и вообще всегда работал с массивами через индексы, так мне понятнее, но вот литература говорит, что обращаться к массиву через указатель правильнее. Отсюда и пошло вот это: lcd_send(*(lcd_font[0]+ch * 5 + i),DTA).

Массив:

Код: Выделить всё

const unsigned char lcd_font[159][5] =
{ 
  0x00, 0x00, 0x00, 0x00, 0x00,  // sp - 0
	0x00, 0x00, 0x2f, 0x00, 0x00,  // ! - 1
	0x00, 0x07, 0x00, 0x07, 0x00,  // " - 2
    ...................
}
Вызов остался прежним:

Код: Выделить всё

  lcd_out(1,3,"test");
Вот на на эту строку я и получаю предупреждение в виде восклицательного знака с подсказкой passing 'char [5]' to parameter of type 'unsigned char *' converts between pointers to integer types with different sign, которое тем не менее отсутствует в окне Build output.

Добавлено after 5 minutes 44 seconds:
Забыл добавить, что вышеуказанное на практике пока не проверил, т.к. дисплей сразу не завелся, пока не понял причину.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ну так в фунции параметр типа "unsigned char *", а посылается в неё "char *". Вот и говорит оно о неявном преобразовании указателей на разные типы - знаковый и беззнаковый.
Контактная информация:
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

Текст (массив символов) по умолчанию считается signed?
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

[uquote="Zhuk72",url="/forum/viewtopic.php?p=3129810#p3129810"]Я изначально и вообще всегда работал с массивами через индексы, так мне понятнее, но вот литература говорит, что обращаться к массиву через указатель правильнее.[/uquote]
Пишите как вам понятнее. Компилятор соптимизирует, а глаза меньше болеть будут от расшифровки. Особенно когда вернётесь править этот код через несколько недель.
[uquote="Zhuk72",url="/forum/viewtopic.php?p=3129847#p3129847"]Текст (массив символов) по умолчанию считается signed?[/uquote]
"Знаковость" типа char в случае отсутствия явного указания signed/unsigned трактуется как правило в зависимости от настроек компилятора/проекта. Прошерстите в этих свойствах.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Язык Си - фантастическая солянка противоречий. Например, типы данных в Си - это просто чудо! Единственный тип, о котором хоть что-то наперед КОНКРЕТНО известно, это int - но известно о нем только то, что это тип со знаком и его размер определяется платформой. А все прочие типы опираются на int и так или иначе (снова по-разному) кратны его размеру.

казалось бы, что может быть проще char-а? это ведь просто байт! но нет: char на самом деле платформозависимый тип и единственное, что про него известно гарантированно, что его размера должно хватать для обозначения кода символа (по-моему, английского алфавита). про знак char-а не сказано ничего конкретного. поэтому формально вполне может быть что char != unsigned char или (зависит от компилятора) char != signed char. соответственно указатель на char может быть как указатель на число со знаком, так и без. существуют платформы, где char занимает больше 8 бит.

именно поэтому в стандарте С99 появились типы гарантированной разрядности int8_t, int16_t, uint16_t и т.д. - но опять-таки формально они не эквивалентны соответствующим стандартным типам аналогичной разрядности. правда, степень этой формальности разная, например, в AVR-GCC все эти intXX_t являются алиасами стандартных... что еще больше запутывает :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

Нашел картинку (просто пример, на выделение не обращайте внимания):
СпойлерИзображение
Опция Plain char as signed в любом виде на предупреждение никак не влияет, С99 тоже.
Ради интереса тикнул вариант Strict ANSI C; в результате при попытке скомпилировать получил 150 ошибок и 10 предупреждений :))
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Реклама
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

Сообщение arkhnchul »

[uquote="ARV",url="/forum/viewtopic.php?p=3129749#p3129749"]А при приращении - надо держать в голове размер данных разыменованного указателя[/uquote]
sizeof? вообще приращение типизированных указателей должно и так само работать с его учетом
Последний раз редактировалось arkhnchul Вт июн 20, 2017 13:56:29, всего редактировалось 1 раз.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

arkhnchul писал(а):sizeof?
что вы хотели этим сказать? например, как sizeof поможет мне разобраться, на сколько изменится значение указателя по записи *ptr++? sizeof тут не липнет - только просмотр исходника до места описания указателя, чтобы вспомнить, что он long int *ptr и поэтому увеличится на 4.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

Сообщение arkhnchul »

[uquote="ARV",url="/forum/viewtopic.php?p=3129926#p3129926"]
arkhnchul писал(а):sizeof?
что вы хотели этим сказать?[/uquote]
это к "держать в голове" :dont_know: честно говоря, могу предположить не так много вариантов, когда из данных, на которые у нас есть указатель, нужно получать значения другого типа и знать для этого их размер. Разве что разгребать какой-нибудь сырой кусок данных в виде uint8_t*, содержащий некие известные структуры.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

[uquote="ARV",url="/forum/viewtopic.php?p=3129749#p3129749"]А при приращении - надо держать в голове размер данных разыменованного указателя, что тоже портит настроение, если в программе много указателей разных типов.[/uquote]
Я бы сказал - немножко иначе, нужно быть аккуратным, чтобы тип указателя при приращении был правильным - а компилятор сам нужное количество байтов отсчитает. Ведь операция проводится над структурированными данными, а количество байтов мало кого из шерифов волнует, как правило. Ну а для именования переменных - проклятая венгерская нотация не совсем уж и бесполезна. ;-)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

использование указателей, с моей точки зрения, примерно в половине случаев как раз и требуется дя ковыряния в сырых данных :) для "логичного" доступа квадратные скобки с индексом понятнее гораздо, да и классическое разыменование тут уместно. выручают так же соглашения об именах переменных. Microsoft, например, страшно любит "префиксы" к переменным, аж скулы сводит от всяких lsptrData :))) во: пока писал, сообщили про венгерскую нотацию - она самая, в яблочко! :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Открыл глаза
Сообщения: 76
Зарегистрирован: Вс июн 18, 2017 08:12:41

Сообщение Зурбаган »

[uquote="Zhuk72",url="/forum/viewtopic.php?p=3129810#p3129810"]void lcd_out (unsigned char row, unsigned char col, unsigned char *text)
{
.....
Вызов остался прежним:

Код: Выделить всё

  lcd_out(1,3,"test");
Вот на на эту строку я и получаю предупреждение .[/uquote]
Вообще-то, если подходить с правильного направления, то та рассматриваемая функция изначально предназначена для работы совместно с одной из "печатающих" функций типа форматной sprint или неформатной "копирующей" strcpy . Это стандартные встроенные функции, поставляемые с компилятором. Правда, встроенная sprintf довольно тяжела по объему и скорости, и потому у нее есть облегченный вариант siprintf с урезанным функционалом, входящий в комплект tiny printf.
Суть этого - получение универсального способа вывода, причем не только на физический дисплей, но и куда угодно, хоть в UART-терминалку, хоть в азбуку Морзе.
Выглядеть это может вот так, на примере вывода двух строк в классический двухстрочник 1602 (на самом деле, эти функции не привязаны к конкретному дисплею)

Код: Выделить всё

#define LINE_LENGTH  (16+1)				// длина строки, плюс символ конца строки
  char txtbuf[LINE_LENGTH * 2] = {0};	// текстовый буфер длиной в 2 строки по (16+1) элементов
  int length;		// длина строки
  int voltage = 0, current = 0; // переменные для значений напряжения и тока

  voltage = 7;
  current = 210;

  length = sprintf(txtbuf, "Voltage: %2i V", voltage);	// первая строка (возвращается число скопированных символов)
  length = sprintf(txtbuf + LINE_LENGTH, "Current: %4i mA", current);  // вторая строка

  /* либо немного иначе, но функция вывода должна распознавать символ переноса строки \n */
  length = sprintf(txtbuf, "Voltage: %2i V\nCurrent: %4i mA", voltage, current);

  write_to_LCD(txtbuf, LINE_LENGTH * 2 );	// выводятся в дисплей две строки сразу
а сама функция просмотра строки для вывода на дисплей будет вот такой:

Код: Выделить всё

int write_to_LCD(char *buf, int lehgth)
{
    /* это заглушка функции */
}
благодаря такой конструкции мы можем выводить в дисплей любые данные - текстовые сообщения, текст с переменной, просто переменную в нужной нам позиции на дисплее

Код: Выделить всё

  sprintf(txtbuf + 5, "%i", voltage);	// вывод только значения переменной в опред.позиции
  sprintf(txtbuf + LINE_LENGTH + 3, "Hello world");	// вывод текста в определенной позиции
  strcpy(txtbuf, "                 ");	// затирается строка

  const char message[] = {"Main messaga"};	// есть некий массив, инициализованный как строка
  strcpy(txtbuf+1, message);				// копируем ее в текстовый буфер для вывода
  strcpy(txtbuf + LINE_LENGTH, "Waka-Waka-shet");  // или пишем напрямую на второй строчке
Таким образом, мы видим, что мы простым способом можем вывести в дисплей любую инфу в любом месте дисплея и нам не требуется изобретать ничего в функции вывода на дисплей. Выбор способа идет на уровне подготовки массива текстового буфера.
Ёшкин кот обормот
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Зурбаган писал(а):Выглядеть это может вот так, на примере вывода двух строк в классический двухстрочник 1602
printf и fprintf смотрятся гораздо органичнее при использовании именно потокового вывода, для чего надо определить одну-единственную функцию вывода символа, я ранее рассказывал (на своём сайте), как это можно сделать. и тогда на самом деле красота: хоть в USART, хоть на дисплей, хоть азбукой Морзе...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Открыл глаза
Сообщения: 76
Зарегистрирован: Вс июн 18, 2017 08:12:41

Сообщение Зурбаган »

Так то оно так, но вы хотите, чтобы у вопрошавшего порвался мозг от многочисленных связей между функциями? :)) Тем более, что судя по всему, у него и так уже он закипел :)
Там, в его случае - графический дисплей. А в графическом дисплее координаты вывода не задаются однозначно строкой. И если иметь дело с пропорциональными шрифтами (у которых разная ширина символа - ifr и Жшы - разной ширины), не получается подравнять вывод "пробелами" и не получается точно угадать занимаемую строкой ширину. Посему, "печатающая" функция должна хорошо взаимодействовать с модулем растровой графики.
Вдобавок, у ARM-ов встроенные "печатающие" функции тянут за собой капец как много всякого хлама от Newlib, и прежде чем взять стандартную printf, двадцать раз подумаешь - а нужно ли тебе вообще это, чтобы напечатать банальное "Напряжение: 12,4 В, Ток: 7,6 А". Это всё можно сделать самописным методом.

[uquote="Zhuk72",url="/forum/viewtopic.php?p=3129847#p3129847"]Текст (массив символов) по умолчанию считается signed?[/uquote]
Он считается как const char, а вот как распознается char без явного указания знака (signed или unsigned) - это уже определяется на уровне принятых компилятором условностей. В вашем случае, char считается как signed char, то есть, знаковым однобайтным. Точно так же как и int без явного указания считается signed int.
Чтобы предупреждений в вашем случае не возникало, нужно принудительно привести тип у вашей строки к запрашиваемому функцией типу. Т.е., (unsigned char*)"Hello world"
Ёшкин кот обормот
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

[uquote="Зурбаган",url="/forum/viewtopic.php?p=3132740#p3132740"]Чтобы предупреждений в вашем случае не возникало, нужно принудительно привести тип у вашей строки к запрашиваемому функцией типу. Т.е., (unsigned char*)"Hello world"[/uquote]
Спасибо, помогло.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Открыл глаза
Сообщения: 40
Зарегистрирован: Вс окт 21, 2012 17:32:00
Откуда: СССР

Сообщение pnp_machinist »

Подскажите как правильно объявить функцию - draw_men.
Вообще то так компилируется и работает. Но однако ругается Keil 5 с stm32.

Код: Выделить всё

struct text_menu
{
 char *bi_1;
 char *bi_2;
 char *bi_3;
 char *bi_4;
 char *bi_5;
 char *bi_6;
 char *bi_7;
 char *bi_8;

}tex_1,tex_12,tex_42,tex_43,tex_44,tex_62,tex_72;       
struct text_menu *lv_1  = &tex_1;                       
struct text_menu *lv_12 = &tex_12;                      


void draw_men(struct text_menu* op,char parag)

{

//тут мой код, что-то делает. Думаю это не так важно.

}
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

[uquote="pnp_machinist",url="/forum/viewtopic.php?p=3149377#p3149377"]Подскажите как правильно объявить функцию - draw_men.
Вообще то так компилируется и работает. Но однако ругается Keil 5 с stm32.[/uquote]
Практика - критерий истины. Исчерпывающее предоставление материала для размышлений не только экономит время тех, кому предлагаете поразмышлять над вашей проблемой, но и стимулирует их к этому. Ругань - в студию! © :)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Открыл глаза
Сообщения: 40
Зарегистрирован: Вс окт 21, 2012 17:32:00
Откуда: СССР

Сообщение pnp_machinist »

[uquote="Siarzhuk",url="/forum/viewtopic.php?p=3149817#p3149817"]Практика - критерий истины. Исчерпывающее предоставление[/uquote]
Если про критерий истины то пожалуйста в личку. :))
Вот так он ругается.

Код: Выделить всё

#223-D: function "draw_men" declared implicitly.
так ругается на попытку объявить
main.c(3): error:  #110: expected either a definition or a tag name
void draw_men(struct *char,char); 
main.c(3): error:  #110: expected either a definition or a tag name
Собственно это весь код проблемы . За исключением главной функции "main".
То что пишет Кейл понятно. Остальное не ясно.... :))
Когда draw_men - ничего не делает т.е. вообще "пустая" Ничего не меняется.
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Сообщение uk8amk »

Код: Выделить всё

main.c(3): error:  #110: expected either a definition or a tag name
void draw_men(struct *char,char);
Вот это прототип функции

Код: Выделить всё

void draw_men(struct text_menu* op,char parag)
{
}
Вот это её реализация

Здесь любой нормальный компилятор материться должен.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

Сообщение Siarzhuk »

[uquote="pnp_machinist",url="/forum/viewtopic.php?p=3149876#p3149876"][uquote="Siarzhuk",url="/forum/viewtopic.php?p=3149817#p3149817"]Практика - критерий истины.[/uquote]
Если про критерий истины то пожалуйста в личку. :))[/uquote]
Как предупреждал Приснопамятный - "Приватно - не консультироваю!" :) Но вообще это была отсылка к первому правилу эксплоатации - "Работает - не трогай!".

[uquote="pnp_machinist",url="/forum/viewtopic.php?p=3149876#p3149876"]void draw_men(struct *char,char);[/uquote]
Во-первы́х - char - это зарезервированное слово языка и именем параметра быть не может, во-вто́рых - тип этого якобы "параметра" указан не полностью... В сюхе, в отличие от плюсов - имя типа структуры типом не является - такштаааа.... © извольте прописать ФИО полностью. Во-третьих - имени структурированного типа там не фигурирует от слова "вапще". ;-)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Ответить

Вернуться в «Разные вопросы по МК»