Например TDA7294

Форум РадиоКот • Просмотр темы - Вопросы по С/С++ (СИ)
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Ср апр 17, 2024 00:16:18

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 7581 ]     ... , , , 249, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 13, 2017 21:06:43 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1289
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4510
Откуда: Планета Земля
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
WiseLord писал(а):
Кстати, странно, что на саму инициализацию массива не ругается.
Видимо, понял задумку программиста и сам разделил по блокам из 5-ти байт :)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 13, 2017 22:04:42 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
ptr должен быть указателем на такой же тип, с такими же квалификаторами, как и lcd_font.

Так и есть. Выше я просто для примера int писал. У себя я написал
Код:
const unsigned char *ptr;

void lcd_out (unsigned char row, unsigned char col, unsigned char *text)
{
  ptr = lcd_font;
......
}

Массив тоже unsigned char, как и указатель, но тем не менее компилятор ругается: a value of type "const unsigned char (*)[5]" cannot be assigned to an entity of type "unsigned char *"

WiseLord писал(а):
Массив-то двумерный, а указатель - на одномерный.
Кстати, странно, что на саму инициализацию массива не ругается.

В источнике этих символов массив представлялся как {{5 байт},{5 байт},{5 байт}, и т.д.}, я по какой-то причине (это было несколько месяцев назад) внутренние {} убрал. Получился одномерный массив, но адресуемый как двухмерный. Я, кстати, такое и раньше делал, ошибок в работе это не вызывало.

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 13, 2017 22:14:04 
Модератор
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1289
Зарегистрирован: Чт мар 18, 2010 23:09:57
Сообщений: 4510
Откуда: Планета Земля
Рейтинг сообщения: 2
Медали: 1
Получил миской по аватаре (1)
Zhuk72 писал(а):
Массив тоже unsigned char, как и указатель, но тем не менее компилятор ругается: a value of type "const unsigned char (*)[5]" cannot be assigned to an entity of type "unsigned char *"

А, ну так правильно. Массив то двумерный.
Вот так надо :
Код:
ptr = lcd_font[0];
если указываем на одну строку.
Или так :
Код:
ptr = &lcd_font[0][0];
если хотим указать на конкретную ячейку.

Добавлено after 6 minutes 42 seconds:
Т.е., в данном случае, мы можем сделать так :
Код:
    ptr = lcd_font[ch];
    for (i = 0; i < 5 ; i++)
    {
      lcd_send(*(ptr + i), DTA);  // или lcd_send(ptr[i]), DTA);
    }
или так :
Код:
    for (i = 0; i < 5 ; i++)
    {
      ptr = &lcd_font[ch][i];
      lcd_send(*ptr,DTA);
    }
Но это будет равносильно этому :
Код:
lcd_send(lcd_font[ch][i],DTA);
где ptr получается лишним.


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 13, 2017 22:26:11 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Спасибо большое, ptr = lcd_font[0]; подошло.
Я так пробовал и раньше, но тогда, видать, мешала ошибка, связанная с константой.
Завтра с отсылкой еще буду разбираться, а пока у меня что-то функция дилей не работает. Собрал все на макетке, прогнал дебаггером, оказалось,что дисплей инициализацию не проходит из-за зацикленной задержки. Что-то я там с SysTick'ом не то сварганил :)

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пн июн 19, 2017 19:43:56 
Открыл глаза

Карма: 1
Рейтинг сообщений: 3
Зарегистрирован: Вс июн 18, 2017 08:12:41
Сообщений: 76
Рейтинг сообщения: 5
ов массив представлялся как {{5 байт},{5 байт},{5 байт}, и т.д.}, ... внутренние {} убрал. Получился одномерный массив, но адресуемый как двухмерный. Я, кстати, такое и раньше делал, ошибок в работе это не вызывало.

В принципе, размерность массива явно указывается при его объявлении количеством скобок []. Внутри него вы можете получать доступ к элементам как угодно, но его размерность от этого не изменится. В регистрах памяти массив, независимо от его размерности, будет располагаться линейно, элемент за элементом, строка за строкой.
В двухмерном массиве array[][] при его инициализации строки можно разделять внутренними скобками {{ , , },{ , , },{ , , },{ , , }}. В одномерном массиве такая запись приведет (может привести) к предупреждению "скобки вокруг скалярной инициализации".

Наверное люди делятся на две категории: одни понимают указатели, другие нет :))

Эт веееерно :) Вообще-то, тут по большей части теоретический вопрос. В умных книшшках много раз описывались указатели, но мало прочесть, надо опробовать самому на деле. И автору (Zhuk72) желательно было бы потренироваться "на кошках", т.е. на простом абстрактном примере, а не влезать сразу к шрифтам и дисплею.
Указатель подобен курсору в текстовом редакторе, или прямоугольной рамке размером в один символ (равносильно char *ptr), и эта рамка может перемещаться по строке текста. Позиция указателя будет отсчитываться от начала строки (т.е. значение переменной ptr, хранящей некоторый адрес из адресного пространства). Рамку можем перемещать в любую позицию. Например, перемещаем на первую букву в выбранном слове ( char *ptr = word1 ) и в рамке видим эту букву. Рамку можем двигать на какое-то число позиций вправо или влево по слову ( ptr += 5; ptr--) и наблюдать в рамке буквы ( a = *ptr ). Номер позиции рамки от начала всей строки мы записываем в свободное место той же строки (переменная ptr сама находится в том же адресном пространтве), а так же в свободном месте строки можем записывать буквы, которые видим в рамке ( переменная, в которую читается по указателю, тоже находится в том же адресном пространстве). Причем, мы можем перескочить за границы интересующего нас слова или вообще попасть туда, где нет текста, но есть место под буквы (перемещаясь по массиву, мы можем запросто выйти за его границы и ошибок компиляции не будет). Причем, буквы могут быть разной ширины, и чтобы увидеть в рамке именно то, что интересует, нужно выбирать рамку строго по ширине конкретной буквы (т.е. указатель и переменная должны быть одного типа (кол-ва байт)). К тому же, буквы могут не быть в составе осмысленных слов (указатели могут указывать на отдельные переменные).

Изображение

Просто так взяв рамку и бросив ее на текст, мы можем попасть на любую букву. Это к слову об использовании неинициализованных указателей, которые могут указывать на любое случайное место. Поэтому, взяв рамку в руки, обязательно определим, какое место в строке нас интересует. То есть, объявив указатель, скажите ему, на что он указывает. В крайнем случае, напишите char *pa = (void*)0, сделав его "нулевым указателем". (чисто технически он указывает на адрес 0 в адресном пространстве). Вместо 0 вы можете записать любой другой адрес, либо получить адрес какой-то переменно с помощью символа &.

Встречается ситуация, когда указатель может указывать на переменную не своего типа. Тогда выдается предупреждение о несовместимости типов переменной и указателя на нее. Образно выражаясь, ширина рамки не совпадает с шириной символа. И если это сделано сознательно, а не в результате ошибки, то можно выполнить приведение типа (подогнать ширину рамки вручную по месту). Вот в таком примере мы сможем четырехбайтную переменную var разложить на отдельные байты в отдельных переменных byte3 - byte0. (обратная последовательность связана с тем, что младший байт имеет больший адрес, чем старший)
Код:
 int var = 0x12345678;
 char *ptr = (char*)&var;    // указатель будет указывать только на 1 байт переменной var

  byte3 = *ptr++;   // чтение переменной по указателю и последующий инкремент указателя, передвигая его на следующий байт
  byte2 = *ptr++;
  byte1 = *ptr++;
  byte0 = *ptr;

Используя возможности приведения типа, можно создать указатель на void, то есть указатель на неопределенный тип переменной, и использовать этот указатель как универсальный, для указания на любой тип. Объясняется это просто - тип void имеет размер в 1 байт (по соглашению в новых редакциях языка)
Код:
  void *pv = (void*)0;    // "нулевой" указатель на void

  int a = 0x12345, x;
  char b = 'A', y;

  pv = &a;              // получает адрес переменной любого типа
  x = *((int*)pv);    // чтение по указателю с приведением указателя к типу читаемой переменной. x = 0x12345

  pv = &b;
  y = *((char*)pv);  // y = 'A'
      /* можно пойти еще дальше и объявить указатель непосредственно на char, который будет выражаться через указатель на void с приведением типа */
  char *pc;
  pc = (char*)pv;
     /* и теперь использовать уже его */
  char symb;
  symb = *pc; // фактически, symb = b непосредственно
  *pc = 'B';  // фактически, b = 'B' непосредственно

без приведения типа указателя компилятор будет выдавать предупреждение о несовместимости типов. А void* - это в большей мере условность, наглядно показывающая универсальный указатель. Этот механизм используется для передачи через параметры функции данных произвольного размера, в том числе и структуры. Параметр функции используется как "универсальный передатчик". Метод используется во FreeRTOS при передаче произвольных параметров в создаваемую задачу.

Вот вкратце и есть суть указателей. Как видим, они используются не только для работы в массивах, но и для создания универсальных взаимосвязей между переменными в разных частях кода. Поэтому освоить указатели - очень даже важно для продвинутого написания кода. "уровень - эдвансд юзер", так сказать :)

------
Что касается доступа к элементам двухмерного массива через индексацию и через указатели, тут вот какая штука.
Допустим, у нас есть двухмерный массив
array[3][5] = {{0,1,2,3,4},{5,6,7,8,9},{10,11,12,13,14}}; с одинаковой длиной строк:
Код:
 0   1   2   3   4
 5   6   7   8   9
10  11  12  13  14

Доступ к произвольному элементу при помощи индексации осуществляется по типу X-Y (не забываем, что индексация происходит с 0, как по горизонтали, так и по вертикали!)
Код:
  char a;
  int x, y;
  x = 2;
  y = 1;
  a = array[y][x];
  a = array[y+1][x-2];

таким способом удобно получать доступ к произвольному элементу по его координатам.
А вот доступ по порядковому номеру (по смещению от начала) удобнее выполняется через указатель.
Код:
  char *ptr = &array[0][0];   // создается указатель на элементы массива и ему сразу присваивается адрес начала массива
  ptr += 8;   // смещение указателя на 8 позиций от начала массива
  a = *ptr;   // получение элемента 8-го массива
  ptr++;   // указатель перемещается на следующий элемент массива
  a = *ptr;   // получение следующего элемента массива
  ptr -= 3; // указатель перемещается на 3 позиции назад от текущей
  a = *ptr;
  a = *ptr++; // получение текущего элемента с последующим смещением указателя на след.элемент
  ptr += (1 * 5); // перемещение указателя на следующую строку ниже. 1 - число строк вниз, 5 - ширина массива (X)
  a = *ptr; // получение элемента строкой ниже (12-й)

однако, как видим, произвольный доступ по координатам X-Y через указатель записывается гораздо хуже, потому что нужно знать именно ширину строки, т.е. количество элементов в строке.
Таким образом, указатели хорошо подходят для последовательного считывания в одномерном или двухмерном массиве. Но указатели усложняют жизнь, когда нужно прочитать некоторую ограниченную область в двухмерном массиве, либо при произвольном доступе в координатах X-Y.
С таким простым шрифтом, как у Zhuk72, можно работать хоть как - по указателю или по индексации, разницы большой нет.

_________________
Ёшкин кот обормот


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Пн июн 19, 2017 20:56:27 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Спасибо большое за такую серьезную работу, это действительно впечатляет!
По указателям я несколько раз читал КиР, смотрел одно обширное видео на ютубе, потому смысл сего чуда представляю.
Но вот когда доходит до практической реализации, у меня в особо сложных случаях шарики за ролики заходят.

Почитаю ваше объяснение, может просветлею в этот раз :D

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 07:17:51 
Открыл глаза

Карма: 1
Рейтинг сообщений: 3
Зарегистрирован: Вс июн 18, 2017 08:12:41
Сообщений: 76
Рейтинг сообщения: 2
Да нет, тут не в практической реализации дело. Судя по вашему первому вопросу, уж извините, дело в теоретических пробелах.
Если в описании функции в параметрах запрашивается указатель, то при вызове функции должен быть передан адрес какой-либо переменной. Почему-то никто явно этого не заметил, а написали, что "ошибка не в указателях" и дальше пошли в какие-то далекие дебри про двухмерные указатели, только лишь мельком зацепившись за несоответствие параметра функции.
А раз так, то разберем детально:
Код:
void lcd_out (unsigned char *text)   // параметр функции в виде указателя
{
   unsigned char ch;     // переменная, в которую будет читаться то, что принято по указателю
   ch = *text;         // собственно, это и есть чтение в переменную по принятому указателю
}

void main(void)
{
  unsigned char symbol = 'A';    // переменная с одиночным символом
  unsigned char message[] = "whattafaka";    // массив переменных в виде строки, инициализированной последовательностю символов
  lcd_out(&symbol);     // вызов функции и передача в нее параметра в виде адреса одиночной переменной

  lcd_out(message);    // вызов функции и передача в нее параметра в виде адреса массива символов.
                       // Без знака &, поскольку имя одномерного массива - это и есть его адрес,
                      //адрес первого его элемента
}

Для той функции, которая была изначально задана, будет работать именно приведенный вариант вызова.
А вот попытка сделать вызов вот так (как поначалу начали советовать):

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

lcd_out((unsigned char*)'A');
Предупреждений нету, но функция делает совсем не то, что ожидалось. А теперь вспомним, что запрашивает параметр? Он запрашивает какой-то адрес. А что есть 'A' ? Это ANSI-представление числа 0х41. То есть, мы явным образом передаем адрес памяти 0х41. Для функции это будет указатель (ссылка) на адрес 0х41. При дальнейшей работе функции идет чтение по принятому в параметре адресу 0х41. Что там физически находится - хрен его знает. Да, работает. Но результат не тот, что ожидался.

Но чтобы раз и навсегда разобраться с вариантами, теперь перепишем немного нашу функцию и попробуем вызвать ее так, как было в вашем первом вопросе:
Код:
void lcd_out (const char *text)
{
   char ch;
   ch = *text;
}

/---
void main(void)
{
    lcd_out("Whattafaka");  // строка символов в качестве параметра
}

И у нас уже замечательнейше работает и выдает то, что и ожидали (однако, предыдущий вариант с адресом массива уже работать не будет).
Именно на этом построены всякие printf, в том числе и самописные.
Так вот видите, где собака зарыта то? А вы говорите "не в указателях дело", да "кавычки не те". В них дело, в них самых. :)

Кстати, можно не извращаться, а для такого случая использовать готовую встроенную sprintf или ее облегченный вариант siprintf из набора tiny_printf. Но об этом - позже.

_________________
Ёшкин кот обормот


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 07:24:21 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Самая большая проблема с указателями, с моей точки зрения, это процесс разыменования и приращения.
При разыменовании надо всегда помнить приоритет этой операции, что частенько порождает кучу скобок, вносящих путаницу.
А при приращении - надо держать в голове размер данных разыменованного указателя, что тоже портит настроение, если в программе много указателей разных типов.

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 10:14:55 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Да нет, тут не в практической реализации дело. Судя по вашему первому вопросу, уж извините, дело в теоретических пробелах.

Для меня реализация в программе - это именно практика. Смысл указателя, получение содержимого по указателю (*) и получение адреса переменной, на который он указывает (&), мне понятны.

Я же писал выше, что у меня получилось избавиться от ошибок.
После исправления у меня получилось так:
Код:
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 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 10:42:43 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1018
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4875
Откуда: Минск
Рейтинг сообщения: 2
Ну так в фунции параметр типа "unsigned char *", а посылается в неё "char *". Вот и говорит оно о неявном преобразовании указателей на разные типы - знаковый и беззнаковый.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 10:57:32 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Текст (массив символов) по умолчанию считается signed?

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 11:12:08 
Потрогал лапой паяльник
Аватар пользователя

Карма: 20
Рейтинг сообщений: 121
Зарегистрирован: Вс янв 19, 2014 22:41:55
Сообщений: 353
Рейтинг сообщения: 2
Я изначально и вообще всегда работал с массивами через индексы, так мне понятнее, но вот литература говорит, что обращаться к массиву через указатель правильнее.

Пишите как вам понятнее. Компилятор соптимизирует, а глаза меньше болеть будут от расшифровки. Особенно когда вернётесь править этот код через несколько недель.
Текст (массив символов) по умолчанию считается signed?

"Знаковость" типа char в случае отсутствия явного указания signed/unsigned трактуется как правило в зависимости от настроек компилятора/проекта. Прошерстите в этих свойствах.

_________________
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 11:19:39 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Язык Си - фантастическая солянка противоречий. Например, типы данных в Си - это просто чудо! Единственный тип, о котором хоть что-то наперед КОНКРЕТНО известно, это 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 являются алиасами стандартных... что еще больше запутывает :)

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 11:41:51 
Сверлит текстолит когтями
Аватар пользователя

Карма: 25
Рейтинг сообщений: 168
Зарегистрирован: Ср янв 29, 2014 08:41:31
Сообщений: 1231
Откуда: Баку
Рейтинг сообщения: 0
Нашел картинку (просто пример, на выделение не обращайте внимания):
СпойлерИзображение

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

_________________
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 13:48:53 
Друг Кота

Карма: 38
Рейтинг сообщений: 618
Зарегистрирован: Пн апр 06, 2015 11:01:53
Сообщений: 3092
Откуда: москва, уфа
Рейтинг сообщения: 0
А при приращении - надо держать в голове размер данных разыменованного указателя

sizeof? вообще приращение типизированных указателей должно и так само работать с его учетом


Последний раз редактировалось arkhnchul Вт июн 20, 2017 13:56:29, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 13:55:17 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
arkhnchul писал(а):
sizeof?
что вы хотели этим сказать? например, как sizeof поможет мне разобраться, на сколько изменится значение указателя по записи *ptr++? sizeof тут не липнет - только просмотр исходника до места описания указателя, чтобы вспомнить, что он long int *ptr и поэтому увеличится на 4.

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 14:05:05 
Друг Кота

Карма: 38
Рейтинг сообщений: 618
Зарегистрирован: Пн апр 06, 2015 11:01:53
Сообщений: 3092
Откуда: москва, уфа
Рейтинг сообщения: 0
arkhnchul писал(а):
sizeof?
что вы хотели этим сказать?

это к "держать в голове" :dont_know: честно говоря, могу предположить не так много вариантов, когда из данных, на которые у нас есть указатель, нужно получать значения другого типа и знать для этого их размер. Разве что разгребать какой-нибудь сырой кусок данных в виде uint8_t*, содержащий некие известные структуры.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 14:09:38 
Потрогал лапой паяльник
Аватар пользователя

Карма: 20
Рейтинг сообщений: 121
Зарегистрирован: Вс янв 19, 2014 22:41:55
Сообщений: 353
Рейтинг сообщения: 0
А при приращении - надо держать в голове размер данных разыменованного указателя, что тоже портит настроение, если в программе много указателей разных типов.

Я бы сказал - немножко иначе, нужно быть аккуратным, чтобы тип указателя при приращении был правильным - а компилятор сам нужное количество байтов отсчитает. Ведь операция проводится над структурированными данными, а количество байтов мало кого из шерифов волнует, как правило. Ну а для именования переменных - проклятая венгерская нотация не совсем уж и бесполезна. ;-)

_________________
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 14:12:16 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
использование указателей, с моей точки зрения, примерно в половине случаев как раз и требуется дя ковыряния в сырых данных :) для "логичного" доступа квадратные скобки с индексом понятнее гораздо, да и классическое разыменование тут уместно. выручают так же соглашения об именах переменных. Microsoft, например, страшно любит "префиксы" к переменным, аж скулы сводит от всяких lsptrData :))) во: пока писал, сообщили про венгерскую нотацию - она самая, в яблочко! :)))

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Вопросы по С/С++ (СИ)
СообщениеДобавлено: Вт июн 20, 2017 22:12:38 
Открыл глаза

Карма: 1
Рейтинг сообщений: 3
Зарегистрирован: Вс июн 18, 2017 08:12:41
Сообщений: 76
Рейтинг сообщения: 0
void lcd_out (unsigned char row, unsigned char col, unsigned char *text)
{
.....
Вызов остался прежним:
Код:
  lcd_out(1,3,"test");

Вот на на эту строку я и получаю предупреждение .

Вообще-то, если подходить с правильного направления, то та рассматриваемая функция изначально предназначена для работы совместно с одной из "печатающих" функций типа форматной 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");  // или пишем напрямую на второй строчке

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

_________________
Ёшкин кот обормот


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 7581 ]     ... , , , 249, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: Google [Bot] и гости: 16


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y