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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

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

Сообщение blackx »

pokk, компилятор отделяет литералы от идентификаторов еще при проведении синтаксического анализа, используя правила их записи, которые исключают всякие неоднозначности. Все "слова" в программе разделяются на:
ключевые: unsigned char, int, extern;
литералы: "Hello", 0x10, 6, 14d, 5, 'C';
идентификаторы: nn, mas, LEN, _hello, a3243;
недопустимые последовательности: 43554acbde, 0myname, 0.555.3, "Hello;

Препроцессор действует точно также, как и компилятор. Сначала разбивает код макроса на синтаксическое дерево - определяет что где на основе заданных признаков (например, если первый символ - цифра или кавычки - значит однозначно не идентификатор), затем уже проводит его семантический анализ - проверяет "смысл" - находится ли идентификатор в списке аргументов макроса, например, или нет, в зависимости от этого заменяет его при обработке макросов или не заменяет. В случае с "nn" - такая запись сразу воспринимается как литерал, и препроцессор его конечно заменить не может.
Изображение only pure true norwegian blackx Изображение
Реклама
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Благодарю за помощь.
Kavka, Во втором примере как раз что надо было.

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

#define TXT_RU(nn) LEN=UTF_8(#nn,mas);send(s,mas,LEN)
как я понял # подставляет " ".
blackx, Я очень часто встречал такую конструкцию

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

#define TXT_RU(nn) do { ....... }  while (0);
и меня всё интересовала для чего она нужна. Но всё таки руки так и не доходили по смотреть.
А тут по приведённой выше ссылки встретил такое
The do and while (0) are a kludge to make it possible to write WARN_IF (arg);, which the resemblance of WARN_IF to a function would make C programmers want to do;

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

  #define WARN_IF(EXP) \
     do { if (EXP) \
             fprintf (stderr, "Warning: " #EXP "\n"); } \
     while (0)
     WARN_IF (x == 0);
          ==> do { if (x == 0)
                fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);
Как я понял из этого, эта конструкция нужна, для того что бы макросу можно было передать x == 0 но как она помогает так и не ясно.
Реклама
BorisSPB
Встал на лапы
Сообщения: 145
Зарегистрирован: Ср фев 01, 2012 10:55:53

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

Сообщение BorisSPB »

Почему в макросах используют do while(0) можно прочитать например здесь.
mastech
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

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

Сообщение mastech »

доброго времени суток тут опять ковыряюсь с Си, много насмотрелся много начитался решил попрактиковаться и понял что ниче не понимаю)) к делу
в общем поставил задачу при нажатии кнопки выводить надпись на дисплей on off, с нуля естественно ничего написать не получиться взял код для дисплея проверил работает надписи выводит и код зажигания диода при нажатии кнопки в теории казалось что ничего сложного нет, как только принялся за дело то понял что и слова связать не могу. Прошу помощи! обьясните доходчиво как и что(на этих двух кусках кода) чувствую что осталось чуть чуть для того чтобы понять как это работает)
Спойлер

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

    #include <avr/io.h>

    int main (void)
    {
    DDRD = 0x00; //порт D - вход
    PORTD = 0xFF; //подключаем нагрузочный резистор
    DDRB = 0xFF; //порт B - выход
    PORTB = 0x00; //устанавливаем 0 на выходе
     
    while(1)
    {
    PORTB = ~PIND; //~ знак поразрядного инвертирования
    }
    }


Спойлер

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

#include <avr/io.h> //библиотека ввода/вывода
#include <util/delay.h>

#define RS 2 //RS=PD2 - сигнал управления ЖКИ
#define E 3 //E=PD3 - сигнал управления ЖКИ



//Программа передачи команд в ЖКИ
void lcd_com (unsigned char lcd)
{ unsigned char temp;

temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда
PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи команды

temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда
PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи команды

_delay_us(111); //Пауза для выполнения команды
}

//Программа записи данных в ЖКИ
void lcd_dat (unsigned char lcd)
{ unsigned char temp;

temp=(lcd|(1<<RS))|(1<<E); //RS=1 – это данные
PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи данных

temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные
PORTD=temp; //Выводим на portD младшую тетраду данных, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи данных

_delay_us(100); //Пауза для вывода данных
}

//Программа иниализации ЖКИ
void lcd_init (void)
{
lcd_com(0x2c); // шина 4 бит, LCD - 2 строки
_delay_us(100);
lcd_com(0x0c); // включение дисплея дисплея, мигающий курсор
_delay_us(100);
lcd_com(0x06); // очистка дисплея
_delay_us(100);

}


//Основная программа
int main()
{
DDRD=0xfc; //Инициализация portD
PORTD=0x00;

_delay_us(100); //Задержка, чтобы ЖКИ успел включиться
lcd_init(); //Инициализация ЖКИ



lcd_com(0x80); //курсор в начало первой строки

lcd_dat('H'); //Вывод "хд44780"
lcd_dat('D');
lcd_dat('4');
lcd_dat('4');
lcd_dat('7');
lcd_dat('8');
lcd_dat('0');



lcd_com(0xc0); //Ставим курсор на начало 2-й строки ЖКИ

lcd_dat('W'); //Записываем "винстар"
lcd_dat('I');
lcd_dat('N');
lcd_dat('S');
lcd_dat('T');
lcd_dat('A');
lcd_dat('R');
lcd_dat(' ');
lcd_dat('L');
lcd_dat('C');
lcd_dat('D');
lcd_dat(')');
lcd_dat(')');
lcd_dat(')');



while(1) //бесконечный цикл

return 1;
}
Реклама
Эиком - электронные компоненты и радиодетали
dzrkot
Открыл глаза
Сообщения: 75
Зарегистрирован: Чт авг 29, 2013 08:02:24

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

Сообщение dzrkot »

mastech писал(а):доброго времени суток тут опять ковыряюсь с Си, много насмотрелся много начитался решил попрактиковаться и понял что ниче не понимаю)) к делу
в общем поставил задачу при нажатии кнопки выводить надпись на дисплей on off, с нуля естественно ничего написать не получиться взял код для дисплея проверил работает надписи выводит и код зажигания диода при нажатии кнопки в теории казалось что ничего сложного нет, как только принялся за дело то понял что и слова связать не могу. Прошу помощи! обьясните доходчиво как и что(на этих двух кусках кода) чувствую что осталось чуть чуть для того чтобы понять как это работает)
Спойлер

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

    #include <avr/io.h>

    int main (void)
    {
    DDRD = 0x00; //порт D - вход
    PORTD = 0xFF; //подключаем нагрузочный резистор
    DDRB = 0xFF; //порт B - выход
    PORTB = 0x00; //устанавливаем 0 на выходе
     
    while(1)
    {
    PORTB = ~PIND; //~ знак поразрядного инвертирования
    }
    }


Спойлер

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

#include <avr/io.h> //библиотека ввода/вывода
#include <util/delay.h>

#define RS 2 //RS=PD2 - сигнал управления ЖКИ
#define E 3 //E=PD3 - сигнал управления ЖКИ



//Программа передачи команд в ЖКИ
void lcd_com (unsigned char lcd)
{ unsigned char temp;

temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда
PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи команды

temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда
PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи команды

_delay_us(111); //Пауза для выполнения команды
}

//Программа записи данных в ЖКИ
void lcd_dat (unsigned char lcd)
{ unsigned char temp;

temp=(lcd|(1<<RS))|(1<<E); //RS=1 – это данные
PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи данных

temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные
PORTD=temp; //Выводим на portD младшую тетраду данных, сигналы RS, E
PORTD=temp&~(1<<E); //Сигнал записи данных

_delay_us(100); //Пауза для вывода данных
}

//Программа иниализации ЖКИ
void lcd_init (void)
{
lcd_com(0x2c); // шина 4 бит, LCD - 2 строки
_delay_us(100);
lcd_com(0x0c); // включение дисплея дисплея, мигающий курсор
_delay_us(100);
lcd_com(0x06); // очистка дисплея
_delay_us(100);

}


//Основная программа
int main()
{
DDRD=0xfc; //Инициализация portD
PORTD=0x00;

_delay_us(100); //Задержка, чтобы ЖКИ успел включиться
lcd_init(); //Инициализация ЖКИ



lcd_com(0x80); //курсор в начало первой строки

lcd_dat('H'); //Вывод "хд44780"
lcd_dat('D');
lcd_dat('4');
lcd_dat('4');
lcd_dat('7');
lcd_dat('8');
lcd_dat('0');



lcd_com(0xc0); //Ставим курсор на начало 2-й строки ЖКИ

lcd_dat('W'); //Записываем "винстар"
lcd_dat('I');
lcd_dat('N');
lcd_dat('S');
lcd_dat('T');
lcd_dat('A');
lcd_dat('R');
lcd_dat(' ');
lcd_dat('L');
lcd_dat('C');
lcd_dat('D');
lcd_dat(')');
lcd_dat(')');
lcd_dat(')');



while(1) //бесконечный цикл

return 1;
}
а что вам тут непонятно то..?
Вообще если хотите понять принцип программирования на С/С++, то лучше возьмите какую-нибудь книгу и прочитайте ( могу посоветовать С.Прата Язык программирования С++, или Дейтл Как программироовать на С++) я именно с этих книг учился, поймёте основы С++, в Си практически всё тоже самое, у меня особо проблем не возникло потом с программирование под С. Лучше этому действительно уделить пару месяцев, и потом уже не задавать таких вопросов, иначе понимание врядли прийдёт к вам...Я на cyberforume начинал, сидел и решалзадачки для студентов +пример и задания из книг, начинал в июле этого года, сейчас уже проблем не испытываю с написанием под мк,вообще думаю взяться за winAPI или в направлении UNIX начинать копать.
Просто до этого я так же, как и вы, знал выборочно базу, читая её по разным сайтам, совет просто как человека, бывшего в вашей ситуации, почитайте норм книги, можно и не С++, а обычный С, но понимание будет и смогёте алгоритмы писать дляуправления теми или иными вещами....Вообщем как-то так...





Три раза просить, что бы Вы прочитали Правила форума, это уже перебор.
Нарушение Правил форума п. 2.7

aen
Реклама
mastech
Грызет канифоль
Сообщения: 269
Зарегистрирован: Чт мар 11, 2010 17:45:37
Откуда: г.фрязино

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

Сообщение mastech »

начитаться я уже начитался, только вот пользоваться не умею/ не получается. мне кажется пару тройку примеров разобрать и пойдет потихоньку.
Вот например в данном примере мне непонятно как сделать чтобы ушла команда на дисплей что взято значение из порта D и после проинвертировано и отправлено в порт B
Реклама
Аватара пользователя
unalex
Мучитель микросхем
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

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

Сообщение unalex »

mastech писал(а):мне непонятно как сделать чтобы ушла команда на дисплей что взято значение из порта D и после проинвертировано и отправлено в порт B
из второго листинга видно что дисплей подключен к порту D, а не к B, в этом и кроется проблема, меняйте его на B и дальше можно думать что посылать и как
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

Парни, привет, такой ленивый и не умный вопрос от меня:
Если я заключу код типа

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

if (cs != 6)
			{
				cs++;
			} 
			else
			{
				cs=1;
			}
в функцию (чтобы удобнее было читать программу и она красивее(о, да, КРАСИВЕЕ!!!11), выглядела, я что-то потеряю в плане памяти и тактов исполнения? Хотя да, наверное, потеряю, это же обращение к функции, переход куда-то, лишний код и т.п... Но так, навскидку, что потеряется по битам\байтам памяти?

UPD: А я нашёл, как код свернуть в "+" :) Так что вопрос отменяется :)
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

Можно еще красивее сделать

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

if (++cs >= 6)	cs=1;
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

shads, я несколько раз перечитал, но не понимаю, как ваш код может быть равен тому, что я написал выше. Может дико туплю, но, правда, я его вижу так:

Если (cs, увеличенное на 1) больше\равно 6, тогда cs=1, иначе идём дальше.

Не помешал бы словарь сокращений :D

UPD: Парни, вот ещё чё. Если мне надо каждую секунду поднимать флаг А, то можно это делать в обработчике прерывания по таймеру. А можно не писать обработчик, а просто проверять, поднят ли флаг данного прерывания в соответствующем регистре? Ну и если поднят, делать то, что хочу и там же его программно сбрасывать. Это я про ATmega AVR.
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

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

Сообщение Psych »

Мikа писал(а):shads, я несколько раз перечитал, но не понимаю, как ваш код может быть равен тому, что я написал выше.
Если ++ стоит впереди, то сначала будет инкремент потом сравнение.
Если расписать подробнее:

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

 cs++;
if (cs >= 6)   cs=1;
Без разницы, скомпилится одинаково.
Мikа писал(а):в функцию (чтобы удобнее было читать программу и она красивее(о, да, КРАСИВЕЕ!!!11),
Забабахайте в inline - размер малость возрастет, но скорость выше будет.
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

Мikа писал(а):не понимаю, как ваш код может быть равен тому, что я написал выше.
В общем суть одна...

Вот ваш вариант:
Изображение

А вот мой вариант:
Изображение
Вложения
2.png
(23.14 КБ) 702 скачивания
1.png
(22.53 КБ) 697 скачиваний
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

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

Сообщение YS »

Забабахайте в inline - размер малость возрастет, но скорость выше будет.
По моему опыту, AVR-GCC (20100110) иногда неадекватно реагирует на явно указанный inline. Но, однако, сам по себе часто инлайнит короткие функции сам, без подсказок.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
unalex
Мучитель микросхем
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

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

Сообщение unalex »

а мне такая красота нравится

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

cs!=6 ? cs++ : cs=1;
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Аватара пользователя
unalex
Мучитель микросхем
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

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

Сообщение unalex »

так тоже прикольно

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

cs = (cs!=6 ? cs : 0) + 1;
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Как в компиляторе IAR при компиляции разместить структуру по определённому адресу ?
делаю вот так вот

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

#pragma location=0x080E0000
NETCONF	NetConf123={1,2,3,4};
Спойлер

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

typedef struct _NETCONF
{
	unsigned char mac[6];
	unsigned long int IP;
        unsigned int port;
	unsigned long int gateway;
	unsigned long int Mask;
	NET_SNMP SNMP;
	unsigned char bord_status;
        unsigned long int IP_list[4];
}NETCONF;
вроде всё нормально компилятор не ругается но и не размешает по заданному адресу возможно из за того что NetConf123 не где не используется.
Этой переменной хочу просто выделить область памяти в которой будут хранится настройки.
При старте программы я из этой области читаю настройки в переменную NetConf (которая находится в озу) и дальше работаю с ней. А в случае когда надо сохранить настройки пишу из NetConf в NetConf123.

А когда пытаюсь считать NetConf123 в главном цикле то выскакивает ошибка

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

Error[Lp025]: absolute section .data (main.o #128) ([0x080e0000-0x080e004b]) overlaps with absolute section .data (main.o #117) ([0x080e0000-0x080e004b]) 
Наверное можно как-то в файле линкера добавить секцию и тд.. но мне не сильно охота его изменять.
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

Парни, огромное спасибо, есть что записть в блокнотик :) Моё непонимание крылось в том, что я считал, что в скобках условия if() действия происходят только для сравнения, а потом отменяются. То есть елси стоит, например c++ > 1, то после проверки с останется не увеличенным на 1 :)
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

shads писал(а):Можно еще красивее сделать

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

if (++cs >= 6)	cs=1;
Скажем так, этот код не равносилен тому что выше у автора вопроса. В исходном варианте если на вход придёт число, большее 6, оно будет инкрементироваться "до посинения" (в смысле, до переполнения, в зависимости от типа char/int/long...). И только после переполнения оно зациклится в диапазоне 1..6. Ваш вариант не имеет такого переполнения, так как проверяется не равенство, а условие больше/равно.

Хотя, скорее всего автор вопроса именно такого поведения и хотел (цикл в диапазоне 1..6), я не вижу, где вариант с переполнением в принципе может быть нужен.

P.S. Я бы вообще как-то так зациклил:
cs = (cs > 5) ? 1 : ++cs
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение Мikа »

WiseLord, да, вы правы, я искал зацикливания 1-6. А щас такой вот вопрос возник.

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

unsigned char a=1;
unsigned char b=0;

void func(unsigned char C)
{
b=c++;
}

func(a);
На словах: есть переменная а. Есть функция, с переменным значением С. Я хочу выполнить функцию, чтобы она посчиталась для а. Но не считается. Я что-то не так написал?
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

А как должно работать?
Я бы предложил другой вариант:

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

 
unsigned char a=1;
unsigned char b=0;

void func(unsigned char c )
{
     return ++c;
}

b=func(a);  
Кстати ваша ошибка кроется возможно в постинкременте
Стоппп а ничего, что c и C это разные переменные?
Ответить

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